CodeMonkey
CodeMonkey

Reputation: 12424

Enumerating DbSet doesn't return to the beginning of the list after enumeration

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

Answers (1)

CodeMonkey
CodeMonkey

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

Related Questions