Reputation: 224
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:
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
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