0

I have an interface defined as:

 public interface IRepository<TEntity> where TEntity : BaseEntity
{
   ...

    IEnumerable<TEntity> Get(
        Expression<Func<TEntity, bool>> filter = null,
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
        string includeProperties = "");
    ...
}

And my implementation as:

public class Repository<TEntity> : IRepository<TEntity> where TEntity : BaseEntity
{
    internal MyContext context;
    internal DbSet<TEntity> dbSet;

    public Repository(MyContext context)
    {
        this.context = context;
        this.dbSet = context.Set<TEntity>();
    }

    public virtual IEnumerable<TEntity> Get(
        Expression<Func<TEntity, bool>> filter = null,
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
        string includeProperties = "")
    {
        IQueryable<TEntity> query = dbSet;

        if (filter != null)
        {
            query = query.Where(filter);
        }

        foreach (var includeProperty in includeProperties.Split
            (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
        {
            query = query.Include(includeProperty);
        }

        if (orderBy != null)
        {
            return orderBy(query).ToList();
        }
        else
        {
            return query.ToList();
        }
    }
}

And finally my code that calls this:

Repository.Get(r =>
            r.SourceOrganisationId == id,
            null, // No ordering
            "DestinationOrganisation") // Include the company
            .Select(d => d.DestinationOrganisation).OrderBy(c => c.Name);

I want to unit test my query, to make sure that I've got the correct where clause, and I'm including an extra entity in the results.

I've been looking at how to mock out the DbContext and DbSet using Moq, but can't see how to still have the EF functionality of the includes. Most of the examples I've found are mocking out a simple GetById. Basically I don't want to mock out EF, just get it to read from in memory rather than from a Db.

Any ideas?

Thanks

ADringer
  • 2,614
  • 36
  • 63
  • 2
    So are you writing unit or integration tests? – kamil-mrzyglod May 04 '16 at 11:17
  • 1
    From a design perspective, if the Repository has no direct need for the `DbContext` then just pass in the `DbSet` in your constructor injection and then mock the `DbSet` which is a lot simpler with moq (IMO) – Nkosi May 04 '16 at 11:27
  • @Kamo I'm writing unit tests, I want to just test my query not the actual data. @Nkosi I've left out parts of the Repository implementation, but I do use the `DbContext` to check/modify state – ADringer May 04 '16 at 12:28
  • Having had a further look into this (and using [this]http://stackoverflow.com/questions/20509315/moqing-enity-framework-6-include-using-dbset) I think it's not really possible to have the `Include` functionality. As the entities are stored in a list they are either always populated with the related entities or not, it can't get retrieve them/remove them based on the `Include` – ADringer May 04 '16 at 13:09

2 Answers2

1

After looking into this some more I've realised what I want to do is not possible.

What I wanted was to mock out the DB with in-memory storage and then test that my queries work including the Include method (e.g. have some tests that include related entities and some that don't). I didn't want to mock out Include I actually wanted it to act as implemented against my in-memory list. This is not possible as from the following here:

One example of such a difference is loading related data. If you create a series of Blogs that each have related Posts, then when using in-memory data the related Posts will always be loaded for each Blog. However, when running against a database the data will only be loaded if you use the Include method.

For this reason, it is recommended to always include some level of end-to-end testing (in addition to your unit tests) to ensure your application works correctly against a database.

ADringer
  • 2,614
  • 36
  • 63
0

There is a tool called Effort which is good for Entity Framework unit testing. Might be worth a look to see if it fits with your requirements?

From their home page:

It is basically an ADO.NET provider that executes all the data operations on a lightweight in-process main memory database instead of a traditional external database

ozz
  • 5,098
  • 1
  • 50
  • 73