Reputation: 4766
I am writing a unit test for my controller. The test uses an actual Repository class that uses a mock dbcontext inside. I am creating the dbset as in this helper article, and it works all fine - except that it only works one time per unit test.
http://codethug.com/2015/03/20/mocking-dbset/
This means that:
IQueryable<User> membersQuery = this.unitOfWork.UserRepository.Get();
List<User> members = membersQuery.ToList(); //here I get 6 members
membersQuery = this.unitOfWork.UserRepository.Get();
members = membersQuery.ToList(); //when its called again, I get 0 members
Why does it behave like that, I would expect that it shoud return the same collection of members both times.
Here is how I create the repository
var enumerable = new List<User>();
// ... populate the mocks list
var mockedContext = new Mock<MyDbContext>();
mockedContext.Setup(c => c.Users).ReturnsDbSet(enumerable);
mockedContext.Setup(c => c.Set<User>()).ReturnsDbSet(enumerable);
var repo = new Mock<IRepository<User>>();
return new Repository<User>(mockedContext.Object, this.logger);
For clarity, some most important bits of the repository code:
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
protected internal MyDbContext Context;
protected internal DbSet<TEntity> DbSet;
public Repository(MyDbContext context)
{
this.Context = context;
this.DbSet = context.Set<TEntity>();
}
public virtual IQueryable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null)
{
IQueryable<TEntity> query = this.DbSet;
if (filter != null)
{
query = query.Where(filter);
}
return query;
}
Any idea why does it work like that?
Upvotes: 2
Views: 479
Reputation: 246998
Based on the linked example. The described problem experienced is usually because of this line.
mockSet.As<IQueryable<T>>()
.Setup(m => m.GetEnumerator())
.Returns(queryableData.GetEnumerator()); //<-- this here
return queryableData.GetEnumerator()
here alony allows for a one time forward only enumeration.
To allow for multiple enumerations return a function.
mockSet.As<IQueryable<T>>()
.Setup(m => m.GetEnumerator())
.Returns(() => queryableData.GetEnumerator()); //<-- note the change () =>
the function will be called every time an enumeration is needed, allowing for multiple enumerations of the collection.
Upvotes: 3