【问题标题】:How should I unit test a repository method implemented with Entity Framework?我应该如何对使用 Entity Framework 实现的存储库方法进行单元测试?
【发布时间】:2014-04-05 14:23:43
【问题描述】:

我的存储库层中有这样的方法:

public IEnumerable<User> GetActiveUsers()
{
    return dbContext.Users
           .Where(u => u.IsActive)
           .OrderBy(u => u.Name)
           .ToList();
}

我应该通过模拟DbContext 来对该方法进行单元测试,还是应该使用实际数据库对其进行测试?

我知道当我使用实际数据库时它不再是“单元”测试,但我没有看到模拟 DbContext 来测试我的存储库方法的价值,这些方法在逻辑上很薄,通常只调用 EF 的方法直接。

如果我必须使用实际的数据库,是否有任何标准策略可以在数据库中填充测试数据,以便测试独立运行并且不会改变数据库中的任何状态?

【问题讨论】:

  • 我还没有使用实体框架(我使用 NHibernate 作为 ORM)但是当我必须测试数据库逻辑时,我使用带有内存数据库的 sqlite。

标签: c# entity-framework unit-testing integration-testing moq


【解决方案1】:

可能不是你想听到的,但你不想嘲笑DbContext。我知道它一直都在完成,在 EF6 中它甚至比以前更容易。还有更多接口和虚拟方法可用于实现模拟对象。从技术上讲,这并不难。

重要的是行为。

即使在您的小示例中,也可能存在问题。模拟 DbSet 将进行区分大小写的排序。连接的DbSet 将从数据库接收排序数据,并且许多数据库排序规则恰好不区分大小写。因此,单元测试可能产生与集成测试不同的结果,即使在这种看似微不足道的情况下也是如此。

内存中的 LINQ 和连接的 LINQ 之间的区别是 overwhelming。就个人而言,我只对涉及任何 LINQ to Entities 查询的任何内容进行集成测试。如果 EF 构建它,创建一个看起来会有所不同的模拟对象图实在是太容易了。在我的服务方法中,我有时会编写非常复杂的查询,可能涉及Includes,可能故意省略null 守卫,知道语句被翻译成SQL,可能涉及一些延迟加载或依赖关系修复。我必须注意实体状态、上下文生命周期、保存更改时启动的验证、并发性......当它被嘲笑时,我只是不相信绿色测试。

当然,还有足够的业务逻辑可以用纯单元测试进行测试。一旦您可以假设正确的对象可用(因为您在集成测试中单独测试),您就可以模拟它们并在内存中对它们的行为进行单元测试。

【讨论】:

    【解决方案2】:

    另一方面:通过建立数据库并针对它进行测试,您会获得哪些额外信息?

    我会简单地模拟 DbContext,因为它最容易维护,而且在本质上对 Entity-Framework 对数据库的调用进行单元测试没有任何价值。

    您要测试的是您的 LINQ 查询是否从数据源返回数据。但是,那些 LINQ 查询被 EF 转换为 SQL 查询是您不会费心的事情。

    如果您真的想测试您的外部依赖项,您可以将其视为额外的集成测试,但 EF 本身已经非常可靠,所以我怀疑这是否有用。

    【讨论】:

      【解决方案3】:

      如果 IEnumerable GetActiveUsers 被实现(并且应该)作为接口,并且您发布的代码是实现该接口的具体类。然后,您通常会使用模拟框架来模拟您实现的接口并返回您设置的结果集。

      正如 Jeroen 所提到的,您通常不需要对实体框架在做什么进行单元测试。单元测试仅测试您的逻辑,而不是其他库(此处为 EF)逻辑。

      【讨论】:

      • 虽然根据定义测试数据库逻辑超出了单元测试的范围,但实际上,考虑到大多数查询都有一些可能包含错误的逻辑,它的结果非常方便。我个人在这种情况下使用 sqllite。
      • 我同意,但我不确定 EF 对 sqlite 的作用与 EF 对 sql server 的作用相同。它可能会产生不同的结果。
      【解决方案4】:

      在为 DBContext 编写 Mock 并执行 LINQ 查询时要记住的是,它们是针对模拟上下文对象运行的 LINQ to OBJECT,而不是 LINQ to Entities... (EF6)...

      我个人会花时间测试这些行为。 Julie Lerman 有一个系列@pluralsight 和 MSDN Mag 在线介绍如何测试 dbContext(如果必须)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-01-15
        • 2014-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多