简体   繁体   中英

Mocking Entity Framework repository pattern

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

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 (eg 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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM