Bartosz
Bartosz

Reputation: 4766

EF repository created from mock db context returns the dbset only once

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

Answers (1)

Nkosi
Nkosi

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

Related Questions