Reputation: 12424
I am using Moq to mock Entity Framework Core's DbSet to return items in a test.
I got a test which gets the first item in the db set and checks its count. At the first time, I manage to get the object stored in the DbSet
and the count is 1. At the second time, I get null in return but the count of the collection is still 1. When I debug and inspect, the collection inside the DbSet gives a message "Enumeration yielded no results"
[TestMethod]
public void MyTest()
{
var dbMock = GetDbContextMock();
Assert.AreEqual(1, dbMock.Object.Table2.Count()); //passes
Table2Model item1 = dbMock.Object.Table2.AsEnumerable().Where(x => x.DataCenter == "DataCenter").FirstOrDefault(); // item1 is an object
Assert.AreEqual(1, dbMock.Object.CurrentRunningServices.Count()); //passes
Table2Model item2 = dbMock.Object.Table2.AsEnumerable().Where(x => x.DataCenter == "DataCenter").FirstOrDefault(); //item2 is null
Assert.AreEqual(1, dbMock.Object.CurrentRunningServices.Count()); //passes
}
Why does the second time I get null instead of an object? It feels like some inner pointer somewhere didn't go back to the start of the collection of the DbSet.
Implementation:
private List<Table2Model> GetMockTable2List()
{
Table2Model item = new Table2Model();
item.DataCenter = "DataCenter";
return new List<Table2Model>() { item } ;
}
private Mock<MyDbContext> GetDbContextMock()
{
var realDal = new MyDbContext();
var dbContextMock = new Mock<MyDbContext>();
dbContextMock.SetupAllProperties();
dbContextMock.Object.Table1= realDal.Table1;
var table2List = GetMockTable2List().AsQueryable();
var table2DbSetMock = new Mock<DbSet<Table2Model>>();
table2DbSetMock.As<IQueryable<Table2Model>>().Setup(m => m.Provider).Returns(table2List.Provider);
table2DbSetMock.As<IQueryable<Table2Model>>().Setup(m => m.Expression).Returns(table2List.Expression);
table2DbSetMock.As<IQueryable<Table2Model>>().Setup(m => m.ElementType).Returns(table2List.ElementType);
table2DbSetMock.As<IQueryable<Table2Model>>().Setup(m => m.GetEnumerator()).Returns(table2List.GetEnumerator());
dbContextMock.Object.Table2 = table2DbSetMock.Object;
return dbContextMock;
}
Upvotes: 1
Views: 133
Reputation: 12424
The problem is with the line
table2DbSetMock.As<IQueryable<Table2Model>>().Setup(m => m.GetEnumerator()).Returns(table2List.GetEnumerator());
It returns the same enumerator every time. The way to fix it is to change the Returns
value to a lambda:
table2DbSetMock.As<IQueryable<Table2Model>>().Setup(m => m.GetEnumerator()).Returns(() => table2List.GetEnumerator());
Upvotes: 2