2016-08-29 18 views
1

我在爲如何編寫我的web api的單元測試而失去id方法的GET。Web API的單元測試,GET相同的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 }; 
} 
+0

您的'TestModelContext'是否具有到數據庫的實際連接或是否是內存中的上下文?我猜你的linq查詢中的'Include'可能導致'product'變量爲'null' – Nkosi

+0

用我的'TestModelContext'更新了 – mimickd

+0

ok,雖然這顯示了一些更多的信息,我們還需要看'TestProductDbSet'因爲這是查詢將執行的對象 – Nkosi

回答

1

根據示例代碼,沒有代碼路徑會導致被測方法返回null

它要麼會返回一個NotFoundResultOkNegotiatedContentResult<Product>

鑑於有可能下試該方法返回一個NotFoundResult,如果if (product == null || product.Count() == 0)條件得到滿足,並且該方法確實返回沒有找到結果,那麼在您的測試

...as OkNegotiatedContentResult<Product>; 

以下嘗試投放NotFoundResultOkNegotiatedContentResult<Product>將導致的結果是null

你應該重新檢查你的設置/配置您的TestModelContext爲您的LINQ呼叫引起product變量是null這反過來又導致要返回的NotFoundResult

UPDATE:

好能開始測試它的基礎上更新的詳細信息,發現一個問題,我應該早發現。

首先,我在將虛假產品添加到列表中時收到錯誤,並且必須更新TestDbSet基類以包含添加的實體。我假設它在示例代碼中被省略了。

public override T Add(T entity) { 
    _data.Add(entity); 
    return entity; 
} 

接下來在被測試的方法中,給定名稱方法和期望在測試中,它應該返回一個單一的Product。當您在測試中進行投射時,您正在返回也會導致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()); 
} 

當進行上述兩項更改時,測試按預期方式通過。

+0

你,我的朋友,是救生員。因爲這個原因,把頭髮從頭上扯下來了幾天。 :) – mimickd

+0

道歉,因爲沒有看到它在代碼更早。只有當我能夠運行我抓住它的例子。我太專注於空條件,並沒有意識到你正在返回查詢 – Nkosi

0

它看起來像控制器返回null作爲結果。產品表格和/或評論表格最有可能不包含您作爲參數傳入網絡方法的值3。

0

這是我懷疑的。您的GetDemoProduct()方法返回您添加的產品沒有Reviews。因此,您的查詢:

var product = (from t in db.Products.Include(t => t.Reviews) 
         .Where(t => t.Id == id) 
         select t); 

沒有返回任何記錄。只是一個想法。如果你可以告訴我們你的GetDemoProduct()那麼我們可以告訴。