模拟 Entity Framework 存储库模式

Mocking Entity Framework repository pattern

我有一个接口定义为:

 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 = "");
    ...
}

我的实现是:

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();
        }
    }
}

最后是调用此代码的我的代码:

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

我想对我的查询进行单元测试,以确保我有正确的 where 子句,并且我在结果中包含了一个额外的实体。

我一直在研究如何使用 Moq 模拟 DbContext 和 DbSet,但看不到如何仍然具有包含的 EF 功能。我发现的大多数示例都模拟了一个简单的 GetById。基本上我不想模拟 EF,只是让它从内存中读取而不是从 Db 中读取。

有什么想法吗?

谢谢

在进一步研究之后,我意识到我想做的事是不可能的。

我想要的是用内存存储模拟数据库,然后测试我的查询是否有效,包括 Include 方法(例如,有一些包含相关实体的测试和一些不包含相关实体的测试) .我不想模拟 Include 我实际上希望它按照我的内存列表执行。这是不可能的,因为从以下 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.

有一个名为 Effort 的工具非常适合 Entity Framework 单元测试。可能值得一看,看看它是否符合您的要求?

来自他们的主页:

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