Reputation: 568
I have tried following the guide using Entity Framework and Moq to mock my context to test my repository.
I'm currently having problems testing my GetSingle
query from my repository:
public Customer GetSingle(int id, HotelBookingContext context = null, params Expression<Func<Customer, object>>[] navigationProperties)
{
using (var tempContext = context ?? new HotelBookingContext())
{
IQueryable<Customer> dbQuery = tempContext.Set<Customer>();
foreach (Expression<Func<Customer, object>> navigationProperty in navigationProperties)
dbQuery = dbQuery.Include(navigationProperty);
return dbQuery
.AsNoTracking()
.FirstOrDefault(x => x.Id == id);
}
}
using the following test:
public void GetSingle_QueryingASingleCustomer_ReturnsASingleCustomer()
{
var cus = new Customer() { Email = "testMail", Name = "testName", Id = 1 };
var customer = new List<Customer> {cus}.AsQueryable();
var mockSet = new Mock<DbSet<Customer>>();
mockSet.As<IQueryable<Customer>>().Setup(m => m.Provider).Returns(customer.Provider);
mockSet.As<IQueryable<Customer>>().Setup(m => m.Expression).Returns(customer.Expression);
mockSet.As<IQueryable<Customer>>().Setup(m => m.ElementType).Returns(customer.ElementType);
mockSet.As<IQueryable<Customer>>().Setup(m => m.GetEnumerator()).Returns(customer.GetEnumerator());
var mockContext = new Mock<HotelBookingContext>();
mockContext.Setup(m => m.Customers).Returns(mockSet.Object);
var temp = _customerRepository.GetSingle(cus.Id, mockContext.Object);
Assert.AreEqual(temp.Name, cus.Name);
Assert.AreEqual(temp.Email, cus.Email);
Assert.AreEqual(temp.Id, cus.Id);
}
If I debug the code I notice that in the GetSingle
function the IQueryable
called dbQuery
remains null
and can therefore not be used in the return statement.
Why is this?
However, if I run it with a real context it works fine.
Upvotes: 1
Views: 1495
Reputation: 247413
That is because in the setup you setup .Customers
property on the mocked context and not the .Set<Customer>()
function. Moq has no clue what to do with that based on the current setup.
mockContext.Setup(m => m.Set<Customer>()).Returns(mockSet.Object);
The above setup should now match the expected behavior of the method under test in its current format.
Other wise if this is the setup...
mockContext.Setup(m => m.Customers).Returns(mockSet.Object);
...then you need to update the method under test to ...
IQueryable<Customer> dbQuery = tempContext.Customers;
for the test to exercise as expected.
Upvotes: 1