Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我应该如何对使用实体框架实现的存储库方法进行单元测试?_C#_Entity Framework_Unit Testing_Integration Testing_Moq - Fatal编程技术网

C# 我应该如何对使用实体框架实现的存储库方法进行单元测试?

C# 我应该如何对使用实体框架实现的存储库方法进行单元测试?,c#,entity-framework,unit-testing,integration-testing,moq,C#,Entity Framework,Unit Testing,Integration Testing,Moq,在我的存储库层中,我有这样一个方法: public IEnumerable<User> GetActiveUsers() { return dbContext.Users .Where(u => u.IsActive) .OrderBy(u => u.Name) .ToList(); } public IEnumerable GetActiveUsers() { 返回dbContext.Users

在我的存储库层中,我有这样一个方法:

public IEnumerable<User> GetActiveUsers()
{
    return dbContext.Users
           .Where(u => u.IsActive)
           .OrderBy(u => u.Name)
           .ToList();
}
public IEnumerable GetActiveUsers()
{
返回dbContext.Users
.其中(u=>u.IsActive)
.OrderBy(u=>u.Name)
.ToList();
}
我应该通过模拟
DbContext
对这个方法进行单元测试,还是应该用实际的数据库进行测试

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


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

另一方面:通过设置数据库并对其进行测试,您会获得哪些额外的信息

我会简单地模拟
DbContext
,因为它最容易维护,而且对实体框架对数据库的调用进行单元测试没有任何价值

您要测试的是LINQ查询是否从数据源返回数据。然而,这些LINQ查询由EF转换为SQL查询,这是您不必担心的


如果你真的想测试你的外部依赖性,你可以把它看作是一个附加的集成测试,但是EF本身已经非常可靠,所以我怀疑它会以任何方式有用。

< P>另一方面:通过建立数据库并测试它,你会得到什么额外的信息? 我会简单地模拟
DbContext
,因为它最容易维护,而且对实体框架对数据库的调用进行单元测试没有任何价值

您要测试的是LINQ查询是否从数据源返回数据。然而,这些LINQ查询由EF转换为SQL查询,这是您不必担心的


如果你真的想测试你的外部依赖关系,你可以把它看作是一个附加的集成测试,但是EF本身已经非常可靠,所以我怀疑这将是有用的。

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


正如Jeroen所提到的,您通常不需要单元测试实体框架在做什么。单元测试只是测试您的逻辑,而不是其他库(这里是EF)逻辑

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


正如Jeroen所提到的,您通常不需要单元测试实体框架在做什么。单元测试只是测试您的逻辑,而不是其他库(这里是EF)逻辑

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

重要的是行为

即使在你的小例子中,也有一个可能的陷阱。模拟的
DbSet
将进行区分大小写的排序。连接的
DbSet
将接收来自数据库的排序数据,许多数据库排序规则恰好不区分大小写。因此,即使在这种看似无关紧要的情况下,单元测试也可能产生与集成测试不同的结果

内存和连接LINQ之间的区别如下所示。就我个人而言,我只对任何涉及LINQ到实体查询的内容进行集成测试。创建一个模拟对象图太容易了,如果EF构建了它,它看起来会有所不同。在我的服务方法中,我有时编写相当复杂的查询,可能涉及
包含
,可能故意省略
null
保护,知道语句已转换为SQL,可能涉及延迟加载或依赖关系修复。我必须了解实体状态、上下文寿命、保存更改时生效的验证、并发性。。。我只是不相信绿色测试,当它被嘲笑的时候


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

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

重要的是行为

即使在你的小例子中,也有一个可能的陷阱。模拟的
DbSet
将进行区分大小写的排序。连接的
DbSet
将接收来自数据库的排序数据,许多数据库排序规则恰好不区分大小写。因此,即使在这种看似无关紧要的情况下,单元测试也可能产生与集成测试不同的结果

内存和连接LINQ之间的区别如下所示。就我个人而言,我只对任何涉及LINQ到实体查询的内容进行集成测试。创建一个模拟对象图太容易了,如果EF构建了它,它看起来会有所不同。在我的服务方法中,我有时编写相当复杂的查询,可能涉及
包含
,可能故意省略