How to write this EF Mock installation code as a reusable common boiler?

I use moq, ef 6 and xunit. I find that I am writing this code again and again, and I thought maybe I could make it a general method, but with some problems.

public static void CreateSalesMock(List<Sale> sales, Mock<DatabaseContext> dbContextMock) { var data = sales.AsQueryable(); var mockSet = new Mock<DbSet<Sale>>(); mockSet.As<IQueryable<Sale>>() .Setup(x => x.Provider) .Returns(data.Provider); mockSet.As<IQueryable<Sale>>() .Setup(x => x.Expression) .Returns(data.Expression); mockSet.As<IQueryable<Sale>>() .Setup(x => x.ElementType) .Returns(data.ElementType); mockSet.As<IQueryable<Sale>>() .Setup(x => x.GetEnumerator()) .Returns(data.GetEnumerator()); dbContextMock.Setup(x => x.Sales).Returns(mockSet.Object); } 

Now I have many other tables in my database, so if I can write one method that takes this data from a list and sets it up so that I can make fun of the query through it, it would be great.

 public static void CreateMockSet<T, TA, TB>(T dataList, TA model, Func<TB> lambda, Mock<DatabaseContext> dbContextMock) where T : List<T> where TA: Mock<DbSet<TA>> { var data = dataList.AsQueryable(); model.As<IQueryable<T>>() .Setup(x => x.Provider) .Returns(data.Provider); model.As<IQueryable<T>>() .Setup(x => x.Expression) .Returns(data.Expression); model.As<IQueryable<T>>() .Setup(x => x.ElementType) .Returns(data.ElementType); model.As<IQueryable<T>>() .Setup(x => x.GetEnumerator()) .Returns(data.GetEnumerator()); dbContextMock.Setup(x => lambda); } 

So far I have it, but I'm not sure if it will work or not. I am stuck in the lambda part (for example, x => x.Sales ), so I can't even check it.

+5
generics c # unit-testing moq entity-framework
source share
1 answer

Tim Larson has already suggested a great solution for this blog code template:

 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 UT, you use it like 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 that allow you to check the 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)); } 
+9
source share

All Articles