【问题标题】:Mocking Entity Framework repository pattern模拟实体框架存储库模式
【发布时间】:2016-05-04 11:15:20
【问题描述】:

我有一个接口定义为:

 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 中读取。

有什么想法吗?

谢谢

【问题讨论】:

  • 那么您是在编写单元测试还是集成测试?
  • 从设计的角度来看,如果存储库没有直接需要DbContext,那么只需在构造函数注入中传入DbSet,然后模拟DbSet,这要简单得多起订量(海事组织)
  • @Kamo 我正在编写单元测试,我只想测试我的查询而不是实际数据。 @Nkosi 我省略了存储库实现的部分内容,但我确实使用 DbContext 来检查/修改状态
  • 进一步研究了这个(并使用 [this]stackoverflow.com/questions/20509315/…)我认为拥有Include 功能是不可能的。由于实体存储在列表中,它们要么总是填充相关实体,要么不填充,因此无法根据Include 检索它们/删除它们

标签: c# entity-framework moq


【解决方案1】:

在研究了更多之后,我意识到我想做的事情是不可能的。

我想要的是用内存存储模拟数据库,然后测试我的查询是否有效,包括 Include 方法(例如,有一些包含相关实体的测试,而一些不包含相关实体)。我不想嘲笑Include 我实际上希望它能够像我的内存列表那样实现。这是不可能的,因为来自以下here

这种差异的一个例子是加载相关数据。如果您创建一系列博客,每个博客都有相关的帖子,那么在使用内存数据时,将始终为每个博客加载相关的帖子。但是,当针对数据库运行时,只有使用 Include 方法才能加载数据。

因此,建议始终包含某种级别的 端到端测试(除了您的单元测试)以确保您的 应用程序针对数据库正常工作。

【讨论】:

    【解决方案2】:

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

    从他们的主页:

    它基本上是一个 ADO.NET 提供程序,它在轻量级进程内主内存数据库而不是传统的外部数据库上执行所有数据操作

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多