How to mock Entity Framework 6 Async methods?

.net, c#, entity-framework, moq, unit-testing

Solution

You are right the problem is in your `InnerDbContext.Set<T>();` statement.

In the current version of the EF (6.0.2) the `DbContext.Set<T>` method is not `virtual` so it cannot be mocked with Moq.

So you cannot easily make your test pass except by changing your design of the `BaseRepository` to not depend on the whole `DbContext` but on one `DbSet<T>`:

So something like:

public BaseRepository(DbSet<T> dbSet)
{
    InnerDbSet = dbSet;
}

Then you can pass directly in your mocked DbSet.

Or you can create a wrapper interface for `DbContext`:

public interface IDbContext
{
    DbSet<T> Set<T>() where T : class;
}

public class TimeSketchContext : DbContext, IDbContext
{
    public virtual DbSet<EmployeeSkill> EmployeeSkill { get; set; }
}

Then use `IDbContext` in your `BaseRepository`:

public class BaseRepository<T> : IRepositoryBase<T> where T : class, IEntity, new()
{
    protected readonly IDbContext InnerDbContext;
    protected DbSet<T> InnerDbSet;

    public BaseRepository(IDbContext innerDbContext)
    {
        InnerDbContext = innerDbContext;
        InnerDbSet = InnerDbContext.Set<T>();
    }

    public virtual Task<T> FindAsync(long id)
    {
        return InnerDbSet.FirstOrDefaultAsync(x => x.Id == id);
    }
}

And finally you just need to change two lines in your test to make it pass:

var mockContext = new Mock<IDbContext>();
mockContext.Setup(c => c.Set<EmployeeSkill>()).Returns(mockSet.Object);

Problem

I am new in mocking. I want to mock up my base repository which is depend on Entity Framework 6 DbContext But I fail. I searched in Google a lot but did not get any sufficient result. At last I got an example at testing with async queries and try to follow but it is worked for me. Here is my code : DbContext : ``` public class TimeSketchContext : DbContext { public virtual DbSet<EmployeeSkill> EmployeeSkill { get; set; } } ``` Base Repository : ``` public class BaseRepository<T> : IRepositoryBase<T> where T : class, IEntity, new() { protected readonly DbContext InnerDbContext; protected DbSet<T> InnerDbSet; public BaseRepository(DbContext innerDbContext) { InnerDbContext = innerDbContext; InnerDbSet = InnerDbContext.Set<T>(); } public virtual Task<T> FindAsync(long id) { return InnerDbSet.FirstOrDefaultAsync(x=>x.Id == id); } ``` } Test : ``` [Fact] public async Task DbTest() { var dummyData = GetEmployeeSkills(); var mockSet = new Mock<DbSet<EmployeeSkill>>(); mockSet.As<IDbAsyncEnumerable<EmployeeSkill>>() .Setup(x => x.GetAsyncEnumerator()) .Returns(new TestDbAsyncEnumerator<EmployeeSkill>(dummyData.GetEnumerator())); mockSet.As<IQueryable<EmployeeSkill>>() .Setup(x => x.Provider) .Returns(new TestDbAsyncQueryProvider<EmployeeSkill>(dummyData.Provider)); mockSet.As<IQueryable<EmployeeSkill>>().Setup(m => m.Expression).Returns(dummyData.Expression); mockSet.As<IQueryable<EmployeeSkill>>().Setup(m => m.ElementType).Returns(dummyData.ElementType); mockSet.As<IQueryable<EmployeeSkill>>().Setup(m => m.GetEnumerator()).Returns(dummyData.GetEnumerator()); var mockContext = new Mock<TimeSketchContext>(); mockContext.Setup(c => c.EmployeeSkill).Returns(mockSet.Object); var baseRepository = new BaseRepository<EmployeeSkill>(mockContext.Object); var data = await baseRepository.FindAsync(1); Assert.NotEqual(null, data); } private EmployeeSkill GetEmployeeSkill() { return new EmployeeSkill { SkillDescription = "SkillDescription", SkillName = "SkillName", Id = 1 }; } private IQueryable<EmployeeSkill> GetEmployeeSkills() { return new List<EmployeeSkill> { GetEmployeeSkill(), GetEmployeeSkill(), GetEmployeeSkill(), }.AsQueryable(); } ``` Result is : Assert.NotEqual() Failure I think problem is ``` public BaseRepository(DbContext innerDbContext) { InnerDbContext = innerDbContext; InnerDbSet = InnerDbContext.Set<T>(); <<<<<<<<<<< } ``` But don`t understand why and how to solve this. I am using : - Visual Studio 2013 Ultimate - Moq - xUnit Thank`s in advance.

Original source

Related problems