Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.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#_.net_Entity Framework_Unit Testing_Mocking - Fatal编程技术网

C# 如何为更改数据的方法编写单元测试?

C# 如何为更改数据的方法编写单元测试?,c#,.net,entity-framework,unit-testing,mocking,C#,.net,Entity Framework,Unit Testing,Mocking,我有以下方法: Void UpdateUser(User user){} 我需要检查这个方法是否能正常工作 我在单元测试中使用了一个单独的db来检查这一点。但是很多有经验的人说,如果我使用这种方法,就不会是单元测试;这就是集成测试 但我不知道如何模拟单元测试 在UpdateUser方法中编写的代码将尝试使用实体框架更新数据 如果我模拟(实际上我也不知道如何做),这将如何与实体框架一起工作?使用事务并在测试结束时回滚您的事务您可以使用事务并回滚,或者创建一个测试用户来尝试其更新。断言,然后在fi

我有以下方法:

Void UpdateUser(User user){}
我需要检查这个方法是否能正常工作

我在单元测试中使用了一个单独的db来检查这一点。但是很多有经验的人说,如果我使用这种方法,就不会是单元测试;这就是集成测试

但我不知道如何模拟单元测试

UpdateUser
方法中编写的代码将尝试使用实体框架更新数据


如果我模拟(实际上我也不知道如何做),这将如何与实体框架一起工作?

使用事务并在测试结束时回滚您的事务

您可以使用事务并回滚,或者创建一个测试用户来尝试其更新。断言,然后在finally块中删除测试用户


您可以使用moq、rhino等模拟框架。moq非常简单,您可以找到许多示例,用类似DI的unity框架演示moq。

模拟意味着您开发软件组件(类)的方式是将任何具有行为的类用作/使用/调用为接口(或抽象类)。你的程序是抽象的。运行时您可以使用一些东西(服务定位器、DI容器、工厂等)来检索/创建这些实例

最常见的方法是使用构造注入。这是一个很好的解释为什么要使用DI,以及如何使用DI的例子

在您的情况下,使用实体框架的组件(例如存储库)必须实现存储库接口,任何使用存储库的类都应该将其用作接口

这样,您可以在单元测试中模拟存储库。这意味着您要创建一个单元测试存储库类(它与任何数据库或EF无关),并在创建要进行单元测试的类的实例时使用它


希望这能有所帮助。有许多来源可以找到。就我个人而言,我刚刚读过,我发现它非常好。是作者的博客。

如果你的班级是这样的话

public class UserRepository()
{
    Sqlcontext _context;
    void UpdateUser(User user)
    {
       _context.Users.Add(user);
    }
}
那么这是不可单元测试的

虽然这不是一个单元测试,但如果您坚持连接数据库并对其进行测试,您可以将函数更改为

User UpdateUser(User user)
{
    _context.Users.Add(user);
    return user;
}
测试一下

user.Id > 0  
在这里,您基本上只是测试实体框架

“我在单元测试中使用了一个单独的db来检查这个问题。但是很多 有经验的人说,如果我用这种方法,那就不会是单位 测试;这就是集成测试。”

那些人是错误的,尽管他们的经验被认为是错误的。出于某种原因,单元测试都是关于孤立地测试代码部分的错误观念近年来越来越流行。事实上,单元测试就是编写作为一个单元的测试,换句话说,它们是孤立存在的,一个单元测试的结果不能影响另一个测试

如果您的
UpdateUser
方法直接访问EF,那么只要确保数据库在每个测试结束时回滚到其启动状态,就可以进行单元测试。但是,为每个测试设置数据库并确保它可以可靠地回滚可能需要很多工作。这就是为什么经常使用mock。其他答案已经涵盖了mcoking EF,所以我不想再重复了


为了大大简化测试,可以在
UpdateUser
和EF之间设置一个外推层。换句话说,
UpdateUser
类提供了一个接口实例,该接口是其进入EF的网关。它不直接与EF对话。然后要模拟EF,只需提供接口的模拟实现。然后,这就把针对EF进行测试的需求推到了一个更基本的层次,具有更基本的CRUD行为。

一个非官方的技巧,而不是最佳实践可以是在测试时使用内存数据库(上下文)。

是的,这就是我正在做的吗?但不管怎样,人们说要嘲笑。我也觉得这是一种很好的编程方式。有数百个博客和数千个关于使用实体框架模拟数据库的问题。您尝试了什么,发现了什么,哪些不起作用?您试图解决的根本问题是如何实现依赖注入。我建议你从那里开始研究。请发布您的自定义数据上下文类-包含
DbSet
属性的类,以便我发布与您的设置匹配的答案。-1回滚数据库正在测试,但不是单元测试。@KeithPayne,请发布关于我所问问题的答案。我必须做单元测试,而不是集成测试。请把你的贵重物品寄出去answer@DavidArno因为不能在单元测试的上下文中锁定数据库以防止另一个进程修改底层数据,所以它不能是确定性的。如果同时运行其他类似的依赖于数据库的测试,并且所有这些测试都没有使用所有其他可能的测试的知识进行编码,以防止意外数据的出现,那么它将失败。与您向其他人展示的假定经验相比,问题不在于隔离,而在于数据库的性质。如果OP在每个线程上使用单独的数据库实例,那么整个数据库的测试可以是一个单元测试。即使是从单独组件跳出的测试也可以是单元测试,只要测试是快速的、自动化的、隔离的和确定性的。确定性是对数据库进行测试时的杀手。没有任何方法可以消除来自其他进程/线程的意外数据的可能性。@KeithPayne,该死,我不得不同意你的看法。:)当考虑并行运行测试时,DB测试实际上不能是单元测试。真正的单元测试必须支持并行运行。