【问题标题】:How to moq Entity Framework SaveChangesAsync?如何最小起订量实体框架 SaveChangesAsync?
【发布时间】:2015-12-23 23:15:18
【问题描述】:
Mock<IDbContext> dbContext;

[TestFixtureSetUp]
public void SetupDbContext()
{
    dbContext = new Mock<IDbContext>();
    dbContext.Setup(c => c.SaveChanges()).Verifiable();
    dbContext.Setup(c => c.SaveChangesAsync()).Verifiable();
    dbContext.Setup(c => c.Customers.Add(It.IsAny<Customer>()))
             .Returns(It.IsAny<Customer>()).Verifiable();
}

[Test]
public async Task AddCustomerAsync()
{
    //Arrange
    var repository = new EntityFrameworkRepository(dbContext.Object);
    var customer = new Customer() { FirstName = "Larry", LastName = "Hughes" };

    //Act
    await repository.AddCustomerAsync(customer);

    //Assert
    dbContext.Verify(c => c.Customers.Add(It.IsAny<Customer>()));
    dbContext.Verify(c => c.SaveChangesAsync());
}

[Test]
public void AddCustomer()
{
    //Arrange
    var repository = new EntityFrameworkRepository(dbContext.Object);
    var customer = new Customer() { FirstName = "Larry", LastName = "Hughes" };

    //Act
    repository.AddCustomer(customer);

    //Assert
    dbContext.Verify(c => c.Customers.Add(It.IsAny<Customer>()));
    dbContext.Verify(c => c.SaveChanges());
}

这就是我要测试的内容:

public class EntityFrameworkRepository
{
    private readonly IDbContext DBContext;

    public EntityFrameworkRepository(IDbContext context)
    {
        DBContext = context;
    }

    public async Task AddCustomerAsync(Customer customer)
    {
        DBContext.Customers.Add(customer);
        await DBContext.SaveChangesAsync();
    }

    public void AddCustomer(Customer customer)
    {
        DBContext.Customers.Add(customer);
        DBContext.SaveChanges();
    }
}

AddCustomers 测试通过。

AddCustomersAsync 测试失败,我在调用await DbContext.SaveChangesAsync() 后不断收到 NullReferenceException。

在 MasonOgCRM.DataAccess.EF.EntityFrameworkRepository.d__2.MoveNext() 在 C:\Users\Mason\Desktop\Repositories\masonogcrm\src\DataAccess.EFRepository\EntityFrameworkRepository.cs:line 43

我在我的代码中看不到任何为空的内容。 DbContext 不为空。 AddCustomers 的等效测试除了不是按预期运行外,其余相同。我怀疑我没有在SetupDBContext() 中正确设置SaveChangesAsync,但我不知道如何修复它。

【问题讨论】:

    标签: c# entity-framework unit-testing async-await moq


    【解决方案1】:

    你可以使用

    dataContext.Setup(x => x.SaveChangesAsync()).ReturnsAsync(1);
    

    dataContext.Verify(x=>x.SaveChangesAsync());
    

    【讨论】:

    • 我使用的是 .Net Core 2.2 SDK,没有 CancellationToken 参数无法工作。 mockMessageContext.Setup(m => m.SaveChangesAsync(It.IsAny())).ReturnsAsync(5);
    • 我正在使用 .netcore 3.1 并同意它不需要取消令牌。但我的验证电话失败了。 mockDb.Verify(a => a.SaveChangesAsync(It.IsAny()),Times.Exactly(2));对模拟的预期调用至少一次,但从未执行:a => a.SaveChangesAsync(It.IsAny())
    • .net 5 还需要 It.IsAny() 来验证 SaveChangesAsync。
    【解决方案2】:

    您是对的,因为您的设置之一不正确 :: dbContext.Setup(c =&gt; c.SaveChangesAsync()).Verifiable();

    该方法返回Task,而您忘记返回Task,因此返回null

    您可以删除dbContext.Setup(c =&gt; c.SaveChangesAsync()).Verifiable(); 或 将设置更改为:

    dbContext.Setup(c => c.SaveChangesAsync()).Returns(() => Task.Run(() =>{})).Verifiable();
    

    【讨论】:

    • 知道了。 SaveChangesAsync 实际上返回了 Task&lt;int&gt;,所以我将设置修改为:dbContext.Setup(c =&gt; c.SaveChangesAsync()).Returns(() =&gt; Task.Run(() =&gt; { return 1; })).Verifiable();,这样就成功了!
    • @mason 你欢迎 :-) 在我看来,我会删除这个设置,除非你使用 VerifyAll,否则它不会给你任何东西
    猜你喜欢
    • 2014-11-18
    • 1970-01-01
    • 2015-02-28
    • 1970-01-01
    • 1970-01-01
    • 2016-01-28
    • 2016-10-09
    • 2021-08-22
    • 2012-11-27
    相关资源
    最近更新 更多