如何moq实体框架SaveChangesAsync?

mas*_*son 10 c# unit-testing entity-framework moq async-await

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());
}
Run Code Online (Sandbox Code Playgroud)

这就是我要测试的内容:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

AddCustomers 测试通过.

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

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

我在代码中看不到任何空的内容.DbContext不是空的.其等效测试AddCustomers与未按预期进行异步运行的情况相同.我怀疑我没有执行正确的安装SaveChangesAsyncSetupDBContext(),但我不知道该做些什么来解决它.

Old*_*Fox 11

你是对的,因为你的一个设置错误:: dbContext.Setup(c => c.SaveChangesAsync()).Verifiable();.

该方法返回a Task并且您忘记返回Task因此null返回.

您可以删除dbContext.Setup(c => c.SaveChangesAsync()).Verifiable();或更改设置,如:

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


Ari*_*tas 6

你可以用

dataContext.Setup(x => x.SaveChangesAsync()).ReturnsAsync(1);
Run Code Online (Sandbox Code Playgroud)

dataContext.Verify(x=>x.SaveChangesAsync());
Run Code Online (Sandbox Code Playgroud)

  • 我使用的是.Net Core 2.2 SDK,无法使用CancellationToken参数。mockMessageContext.Setup(m =&gt; m.SaveChangesAsync(It.IsAny &lt;CancellationToken&gt;()))。ReturnsAsync(5); (3认同)