Enumerating a Moq'ed IDbSet throws exception: "Collection was modified; enumeration operation may not execute."

Viewed 423

I'm trying to Mock IDbSet using the Moq framework. The unit test should add a new record (entity) to an existing Mocked DbSet collection (SetUp) and return the count of the new collection.

My TestInitialize Setup looks like:

public class BlogTests
    {
        private IRepository _repository;

        [TestInitialize]
                public void Setup()
                {
                    var blogEntries = new List<BlogEntry>
                    {
                        new BlogEntry()
                        {
                            //...init the object
                        }
                    };
                    var queryableBlogEntries = QueryableDbSetMock.GetQueryableMockDbSet<BlogEntry>(blogEntries);
                    var repoMock = new Mock<IRepository>();
                    repoMock.Setup(x => x.BlogEntries).Returns(queryableBlogEntries);
                    _repository = repoMock.Object;
                }

And here is the method which returns a mock IDbSet, given a List:

public class QueryableDbSetMock
    {
        public static IDbSet<T> GetQueryableMockDbSet<T>(List<T> sourceList) where T : class
        {
            var queryable = sourceList.AsQueryable();

            var dbSet = new Mock<IDbSet<T>>();
            dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
            dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
            dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
            dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator());
            dbSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>(s => sourceList.Add(s)); 
            return dbSet.Object;
        }
    }

In the unit test I would arrange a new BlogEntry object and try to add it to the mocked IDbSet, after which I would expect the total count of the collection to be two elements/records.

The following Unit Test succeeds:

public void IndexTest()
        {
            //Arrange
            var entries = _repository.BlogEntries;

            var newEntry = new BlogEntry()
            {
                //...init the second object
            };

            //Act
            entries.Add(newEntry);
            var count = entries.Count();

            //Assert
            Assert.AreEqual(2, count);
        }

But when I try to do the counting using the GetEnumerator method, the Enumerator.MoveNext command will throw the exception:

'System.InvalidOperationException: 'Collection was modified; enumeration operation may not execute.' '.

Here is the code of the altered Unit Test:

[TestMethod()]
        public void IndexTest2()
        {
            //Arrange
            var entries = _repository.BlogEntries;

            var newEntry = new BlogEntry()
            {
                //...init the second object
            };

            //Act
            entries.Add(newEntry);
            var enumerator = entries.GetEnumerator();
            int count = 0;
            while (enumerator.MoveNext()) //Throws Exception
            {
                count++;
            }
            //Assert
            Assert.AreEqual(2, count);
        }

So my confusion lies in the fact that the first Unit Test seems to have no problems in calculating the count of the altered collection, but when trying to do the counting kind of the hard way, the Test fails.

Any clarification on this would be highly appreciated!

1 Answers
Related