简体   繁体   中英

How to moq Entity Framework SaveChangesAsync?

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());
}

And here's what I want to test:

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 test passes.

AddCustomersAsync test fails, I keep getting a NullReferenceException after calling await DbContext.SaveChangesAsync() .

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

I can't see anything that's null in my code. DbContext is not null. The equivalent test of AddCustomers which is identical with the exception of not being async runs as expected. I suspect I haven't performed a correct setup of SaveChangesAsync in SetupDBContext() but I don't know what to do to fix it.

You are right the problem occurs because one of your setups incorrect :: dbContext.Setup(c => c.SaveChangesAsync()).Verifiable(); .

The method return a Task and you forgot to return a Task therefore null returns.

You can remove dbContext.Setup(c => c.SaveChangesAsync()).Verifiable(); or change the setup to something like:

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

You could use

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

and

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

This worked for me:

dbContext.Verify(m => m.SaveChangesAsync(It.IsAny<CancellationToken>()), Times.Once());

It may also require a cancellation token, so something like this should work:

dataContext.Setup(x => x.SaveChangesAsync(It.IsAny<CancellationToken>())).ReturnsAsync(1);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM