Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 924
mason Avatar asked Sep 26 '15 04:09

mason


2 Answers

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();
like image 154
Old Fox Avatar answered Oct 09 '22 13:10

Old Fox


You could use

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

and

dataContext.Verify(x=>x.SaveChangesAsync());
like image 41
Arijus Gilbrantas Avatar answered Oct 09 '22 13:10

Arijus Gilbrantas