我不知道如何为我的Web API GET by id方法编写单元测试。
这是我所拥有的:
public void GetProduct_ShouldReturnSameID()
{
var context = new TestModelContext();
context.Products.Add(GetDemoProduct());
var controller = new ProductsController(context);
var result = controller.GetProduct(3) as OkNegotiatedContentResult<Product>;
Assert.IsNotNull(result);
Assert.AreEqual(3, result.Content.Id);
}
我正在尝试测试的控制器方法
public IHttpActionResult GetProduct(int id)
{
var product = (from t in db.Products.Include(t => t.Reviews)
.Where(t => t.Id == id)
select t);
if (product == null || product.Count() == 0)
{
return NotFound();
}
return Ok(product);
}
我的测试可以在其他控制器上找到,但不能找到这个控制器。我想知道这是怎么回事?我的测试失败并显示
“预期:不为空,但为:空”
public class TestModelContext : IModelContext {
public TestModelContext() {
this.Products = new TestProductDbSet();
}
public DbSet<Product> Products { get; set; }
public int SaveChanges() {
return 0;
}
public void MarkAsModified(Product item) { }
public void Dispose() { }
}
public class TestProductDbSet : TestDbSet<Product> {
public override Product Find(params object[] keyValues) {
return this.SingleOrDefault(product => product.Id == (int)keyValues.Single());
}
}
public class TestDbSet<T> : DbSet<T>, IQueryable, IEnumerable<T>
where T : class
{
ObservableCollection<T> _data;
IQueryable _query;
public TestDbSet()
{
_data = new ObservableCollection<T>();
_query = _data.AsQueryable();
}
// ...
public override T Create()
{
return Activator.CreateInstance<T>();
}
public override TDerivedEntity Create<TDerivedEntity>()
{
return Activator.CreateInstance<TDerivedEntity>();
}
public override ObservableCollection<T> Local
{
get { return new ObservableCollection<T>(_data); }
}
Type IQueryable.ElementType
{
get { return _query.ElementType; }
}
System.Linq.Expressions.Expression IQueryable.Expression
{
get { return _query.Expression; }
}
IQueryProvider IQueryable.Provider
{
get { return _query.Provider; }
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _data.GetEnumerator();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return _data.GetEnumerator();
}
}
GetDemoProduct:
Product GetDemoProduct()
{
return new Product() { Id = 3, Name = "Name", Reviews = null };
}
根据示例代码,没有代码路径会导致被测方法返回null
。
它会返回aNotFoundResult
或aOkNegotiatedContentResult<Product>
假设被测方法有可能返回a NotFoundResult
,如果满足if (product == null || product.Count() == 0)
条件且该方法确实返回了未找到结果,则测试中的以下内容
...as OkNegotiatedContentResult<Product>;
尝试将其强制转换NotFoundResult
为OkNegotiatedContentResult<Product>
将导致结果为null
。
您应该重新检查自己的设置/配置,TestModelContext
因为您的linq调用导致product
变量变为null
,进而导致NotFoundResult
返回。
更新:
Ok能够根据您更新的详细信息开始对其进行测试,并发现了我应该早已注意到的问题。
首先,将假冒产品添加到列表时,我不得不报错,并且不得不更新TestDbSet基类以包括添加的实体。我假设它在示例代码中被省略了。
public override T Add(T entity) {
_data.Add(entity);
return entity;
}
接下来在被测方法中,给定名称方法和测试中的期望值,它应该返回单个产品。您正在返回查询,当您在测试中进行转换时,该查询也将导致null。
public IHttpActionResult GetProduct(int id) {
var product = (from t in db.Products.Include(t => t.Reviews)
.Where(t => t.Id == id)
select t);
if (product == null || product.Count() == 0) {
return NotFound();
}
return Ok(product.First());
}
进行上述两个更改后,测试按预期通过。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句