2016-11-08 80 views
-1

我想創建一個測試來測試實體框架Add方法。任何人都可以幫助如何嘲笑DbSet.Add方法。我嘗試了以下但不工作。我究竟做錯了什麼?C#如何Moq entityframework DbSet添加方法

我得到的結果是nullrepository.Insert後...

test.cs中:

var productToCreate = new Product { Name = "Added", Description = "Added" };   

var result = repository.InsertAsync(objToCreate, userContext).Result; 
Assert.AreEqual(result.Name, "Added"); 

Mock.cs

internal static DbSet<T> GetMockedDataSet<T>(IEnumerable<T> data) where T : class 
{ 
    // Create a mocked data set that contains the data 
    var set = new Mock<DbSet<T>>(); 
    set.As<IDbAsyncEnumerable<T>>() 
     .Setup(m => m.GetAsyncEnumerator()) 
     .Returns(new TestDbAsyncEnumerator<T>(data.GetEnumerator())); 
    set.As<IQueryable<T>>() 
     .Setup(m => m.Provider) 
     .Returns(new TestDbAsyncQueryProvider<T>(data.AsQueryable().Provider)); 
    set.As<IQueryable<T>>().Setup(m => m.Expression).Returns(data.AsQueryable().Expression); 
    set.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(data.AsQueryable().ElementType); 
    set.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator()); 

    set.Setup(x => x.AsNoTracking()).Returns(set.Object); 
    set.Setup(x => x.Add(It.IsAny<T>())).Callback<T>((s) => data.Concat(new[] { s })); 

    // Return the mock 
    return set.Object; 
} 

庫:

public async Task<Product> InsertAsync(Product input) 
{ 
    using (var ctx = .....)) 
    { 
     var added = ctx.Set<Product>().Add(input); 

     await ctx.ValidateAndSaveAsync(); 

     return added; 
    } 
} 
+1

提供一個能夠再現問題的[mcve]。 – Nkosi

+0

@Nkosi,對不起,我不明白你是什麼意思?我提供了我的代碼塊並解釋了我期待的內容?謝謝 –

+1

這個例子不完整。能夠重新創建問題的因變量太多,測試中的方法與測試中顯示的不同,顯示的設置不完整....需要繼續嗎? – Nkosi

回答

2

根據如何Add方法在測試所採用的方法...

var added = ctx.Set<Product>().Add(input); 

...也應該有在返回已輸入的參數設置一個Returns,如果是這樣的期望功能。

set.Setup(x => x.Add(It.IsAny<T>())) 
    .Returns<T>(arg => arg) 
    .Callback<T>((s) => data.Concat(new[] { s })); 

但考慮到有關的上下文相關性的信息是未知...

using (var ctx = .....)) 

這是不確定的,如果所提供的解決方案將收到預期的效果。

此外,如果測試異步方法,請不要混合使用異步和同步調用。以下行...

var result = repository.InsertAsync(objToCreate, userContext).Result; 

...可能導致死鎖。

使測試方法一路異步。

[TestMethod] 
public async Task InsertAsync_Should_Return_Product() { 
    //...other code 

    var expected = new Product { Name = "Added", Description = "Added" };   

    var actual = await repository.InsertAsync(expected, userContext); 

    Assert.AreEqual(expected.Name, actual.Name); 
} 
+0

哇!它像魅力一樣工作。謝謝。我改變了testmethod以使用異步。再次感謝 –

+0

附註 - 您對add方法的回調沒有做任何事情。它對提供的原始收集沒有影響。 – Nkosi