How to write this EF Mock setup code as a reusable Generic Boilerplate?

Tim Larson already offered a great solution for this boilerplate code in his blog:

public static class DbSetMocking
{
    private static Mock<DbSet<T>> CreateMockSet<T>(IQueryable<T> data)
            where T : class
    {
        var queryableData = data.AsQueryable();
        var mockSet = new Mock<DbSet<T>>();
        mockSet.As<IQueryable<T>>().Setup(m => m.Provider)
                .Returns(queryableData.Provider);
        mockSet.As<IQueryable<T>>().Setup(m => m.Expression)
                .Returns(queryableData.Expression);
        mockSet.As<IQueryable<T>>().Setup(m => m.ElementType)
                .Returns(queryableData.ElementType);
        mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator())
                .Returns(queryableData.GetEnumerator());
        return mockSet;
    }

    public static IReturnsResult<TContext> ReturnsDbSet<TEntity, TContext>(
            this IReturns<TContext, DbSet<TEntity>> setup,
            TEntity[] entities)
        where TEntity : class
        where TContext : DbContext
    {
        Mock<DbSet<TEntity>> mockSet;
        return ReturnsDbSet(setup, entities, out mockSet);
    }

    public static IReturnsResult<TContext> ReturnsDbSet<TEntity, TContext>(
            this IReturns<TContext, DbSet<TEntity>> setup,
            IQueryable<TEntity> entities)
        where TEntity : class
        where TContext : DbContext
    {

        Mock<DbSet<TEntity>> mockSet;
        return ReturnsDbSet(setup, entities, out mockSet);
    }

    public static IReturnsResult<TContext> ReturnsDbSet<TEntity, TContext>(
            this IReturns<TContext, DbSet<TEntity>> setup,
            IEnumerable<TEntity> entities)
        where TEntity : class
        where TContext : DbContext
    {
        Mock<DbSet<TEntity>> mockSet;
        return ReturnsDbSet(setup, entities, out mockSet);
    }

    public static IReturnsResult<TContext> ReturnsDbSet<TEntity, TContext>(
    this IReturns<TContext, DbSet<TEntity>> setup,
    TEntity[] entities, out Mock<DbSet<TEntity>> mockSet)
        where TEntity : class
        where TContext : DbContext
    {
        mockSet = CreateMockSet(entities.AsQueryable());
        return setup.Returns(mockSet.Object);
    }

    public static IReturnsResult<TContext> ReturnsDbSet<TEntity, TContext>(
            this IReturns<TContext, DbSet<TEntity>> setup,
            IQueryable<TEntity> entities, out Mock<DbSet<TEntity>> mockSet)
        where TEntity : class
        where TContext : DbContext
    {

        mockSet = CreateMockSet(entities);
        return setup.Returns(mockSet.Object);
    }

    public static IReturnsResult<TContext> ReturnsDbSet<TEntity, TContext>(
    this IReturns<TContext, DbSet<TEntity>> setup,
    IEnumerable<TEntity> entities, out Mock<DbSet<TEntity>> mockSet)
        where TEntity : class
        where TContext : DbContext
    {
        mockSet = CreateMockSet(entities.AsQueryable());
        return setup.Returns(mockSet.Object);
    }

}

Then in the UT you use it as the following:

var context = new Mock<DatabaseContext>();
context.setup(x => x.Sales).ReturnsDbSet(new List<Sale>(){put here the items..});

Edit

I updated the code. Now there are 3 more overloads which allows verification on DbSet<T> property:

    [TestMethod]
    public void TestMethod1()
    {
        var sales = new List<Sale>
        {
            new Sale() {id = 1},
            new Sale() {id = 6},
            new Sale() {id = 5},
            new Sale() {id = 4},
            new Sale() {id = 3},
            new Sale() {id = 2}
        };
        var fakeContest = new Mock<SalesContext>();
        Mock<DbSet<Sale>> fakeSet;
        fakeContest.Setup(context => context.Sales).ReturnsDbSet(sales, out fakeSet);

        var itemsToRemove = sales.Where(sale => sale.id%2 == 0);


        fakeContest.Object.Sales.RemoveRange(itemsToRemove);


        fakeSet.Verify(set => set.RemoveRange(itemsToRemove));

    }

Leave a Comment