Florian Falk
Florian Falk

Reputation: 224

Mocking verify DbSet failed with GetEnumerator unverified

I'm trying to mock our database with moq right now. Here I have the problem that some methods from the EntityFramework return DbSet objects which I iterate over in my code using foreach.

Now I call VerifyNoOtherCalls(); at the end of the defined test methods.But here the test blows up in my face, because the foreach loop calls GetEnumerator() from the IEnumerable Interface, which I don't verify. But this is not possible because the DbSet itself does not implement GetEnumerator() and moq does not allow to call a ToList() in the Lambda.

Now I have two questions:

  1. How is it possible that DbSet implements the IEnumerable interface but does not implement the GetEnumerator method directly or in the base class?
  2. how do I get the test running? I have already found several instructions on the internet, so I have decided to mock DbSet myself:
        public static DbSet<T> GetQueryableMockDbSet<T>(List<T> sourceList) where T : class
        {
            var queryable = sourceList.AsQueryable();

            var dbSet = new Mock<DbSet<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;
        }

However, this does not work either.

Upvotes: 1

Views: 567

Answers (1)

StriplingWarrior
StriplingWarrior

Reputation: 156459

To your first question, DbSet<> has an explicit implementation for IQueryable.GetEnumerator(). This allows DbSets to be used as IEnumerable<>s without cluttering intellisense and such with methods that aren't typically called on the DbSet directly.

I'm not positive why the code you've posted isn't working, but you can try mocking the GetEnumerator() on dbSet.AsIEnumerable<T>().

At a higher level, though, I've found there's little value in mocking the DbSet (treating it like a service whose methods you need to mock and verify). I would focus on faking it (treating it like a collection, whose contents you can specify). So calling VerifyNoOtherCalls() is probably not helpful, based on my experience.

Upvotes: 1

Related Questions