Unit Test for EF LINQ queries using Mocked DbSet

Goal: 

Create a unit test for a EF repository query. As we all know unit tests are infrastructure agnostic and therefore have no kowledge of for example external services, databases, etc. So how can we create a unit test for a repository query without hitting the DB? Mocked DbSet to the rescue:

Solution:

Create an extension method on collections that can be used to mock the data/collections returned by EF instead of hitting the DB.

//A List of allocations for a gas system that we want to return when the EF LINQ query is executed

var allocationVOMockDbSet = new List

{

new AllocationVO

{

LocationId = -1,

ContractId = -1,

NominationId = null,

AllocatedQuantity = 1000,

AdjustmentIndicatorType = AdjustmentIndicatorType.Measurement,

GasDayId = -100,

GasDay = new GasDay(null, DateTime.Today),

AccountingPeriod = new YearMonth(2016, 10)

},

//new

new AllocationVO

{

LocationId = -1,

ContractId = -1,

NominationId = null,

AllocatedQuantity = 1500,

AdjustmentIndicatorType = AdjustmentIndicatorType.Other,

GasDayId = -100,

GasDay = new GasDay(null, DateTime.Today),

AccountingPeriod = new YearMonth(2016, 10)

},

}

.AsMockDbSet();  //here we define the list as a mocked set

//Now we use the StructureMap container to create an inject the DbContext of IAfterFlowContext

var afterFlowContextMock = thisContainer.InstantiateAndInjectMock();

//Now we add the setup for the mocked context on Set of AllocationVO (a domain entity) that returns the mocked set

afterFlowContextMock.Setup(s => s.Set()).Returns(allocationVOMockDbSet.Object);

//Here is the extension for collections on DbSet that makes it possible to mock all the different implementations of the DbSet

public static Mock<DbSet> AsMockDbSet(this ICollection source) where T : class

{

var queryable = source.AsQueryable();

var dbSet = new Mock<DbSet>();

dbSet.As<IQueryable>().Setup(m => m.Provider).Returns(queryable.Provider);

dbSet.As<IQueryable>().Setup(m => m.Expression).Returns(queryable.Expression);

dbSet.As<IQueryable>().Setup(m => m.ElementType).Returns(queryable.ElementType);

dbSet.As<IQueryable>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator);

dbSet.Setup(s => s.Add(It.IsAny())).Callback(source.Add);

dbSet.Setup(s => s.Include(It.IsAny())).Returns(dbSet.Object);

dbSet.Setup(x => x.AsNoTracking()).Returns(dbSet.Object);

return dbSet;

}

New on Geeks with Blogs