Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.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# TDD:.NET遵循TDD原则,模拟/不模拟?_C#_.net_Mocking_Tdd - Fatal编程技术网

C# TDD:.NET遵循TDD原则,模拟/不模拟?

C# TDD:.NET遵循TDD原则,模拟/不模拟?,c#,.net,mocking,tdd,C#,.net,Mocking,Tdd,我正在努力跟踪TDD,我遇到了一个小问题。我编写了一个将新用户插入数据库的测试。在MyService类上调用了Insert新用户,所以我继续创建了mytest。它失败了,我开始在MyService类上实现CreateUser方法 我遇到的问题是MyService将调用存储库(另一个类)来执行数据库插入 所以我想我会使用模拟框架来模拟这个存储库类,但这是正确的方法吗 这意味着我必须更改我的测试,以便为我的用户存储库实际创建一个模拟。但这是推荐的吗?我最初编写了测试,但失败了,现在我意识到我需要一个

我正在努力跟踪TDD,我遇到了一个小问题。我编写了一个将新用户插入数据库的测试。在MyService类上调用了Insert新用户,所以我继续创建了mytest。它失败了,我开始在MyService类上实现CreateUser方法

我遇到的问题是MyService将调用存储库(另一个类)来执行数据库插入

所以我想我会使用模拟框架来模拟这个存储库类,但这是正确的方法吗

这意味着我必须更改我的测试,以便为我的用户存储库实际创建一个模拟。但这是推荐的吗?我最初编写了测试,但失败了,现在我意识到我需要一个存储库,需要模拟它,所以我必须更改测试以适应模拟对象。有点臭

我希望这里有一些反馈

如果是这样的话,那么我什么时候才能创建实际的用户存储库?这需要它自己的测试吗

还是我应该忘记嘲笑什么?但这将被归类为集成测试而不是单元测试,因为我将把MyService和用户存储库作为一个单元一起测试


我有点迷路了;我想从正确的方式开始。

您肯定会模拟对数据库的依赖关系,然后在服务上断言在模拟上调用预期的方法。我赞扬你们努力遵循最佳实践,并鼓励你们继续走这条道路。 正如您现在所意识到的,随着您的继续,您将开始向您编写的类添加新的依赖项。 我强烈建议您在外部满足这些依赖关系,如创建接口IUserRepository,这样您就可以模拟它,并将IUserRepository传递给服务的构造函数。 然后将其存储在实例变量中,并调用需要的方法(即_userRepository.StoreUser(user))。 这样做的好处是,可以很容易地从测试类中满足这些依赖关系,并且可以将对象的实例化和生命周期管理作为一个单独的问题来考虑

tl;博士:创建一个模拟

所以我想我会用一个模拟框架来模拟这个 存储库类,但这是正确的方法吗

是的,这是一种完全正确的方法,因为您应该单独测试您的类。即通过模拟所有依赖项。否则,您无法判断您的类是失败的还是它的某些依赖项

最初我写了测试,结果失败了,现在我意识到我需要一个 并且需要模拟它,所以我不得不改变我的测试 为了迎合被模仿的对象。有点臭

提取类、重新组织方法等是一种重构。测试在这里帮助您进行重构,消除对更改的恐惧。如果实现发生更改,则更改测试是完全正常的。我相信你不认为你可以从第一次尝试中创造出完美的代码,并且永远不再更改它

如果是这样的话,我什么时候才能创建真正的用户呢 存储库?这需要它自己的测试吗

您将在应用程序中创建一个真正的存储库。您还可以为此存储库编写测试(即,检查它是否正确调用了底层数据访问提供程序,应该对其进行模拟)。但是这样的测试通常非常耗时和脆弱。因此,最好编写一些验收测试,用真实的存储库测试整个应用程序

还是我应该忘记嘲笑什么


恰恰相反,您应该使用mock单独测试类。如果模拟需要大量工作(数据访问、ui),那么不要模拟此类资源,在集成或验收测试中使用真实对象。

我有两套测试库。一个用于单元测试,我在其中模拟东西。我只在那里测试单元。因此,如果我在服务中有一个AddUser方法,我将创建所有mock,以便能够在该特定方法中测试代码。 这使我有可能测试一些我无法验证的代码路径

另一个测试库用于集成测试、功能测试或任何您想称之为的测试。这一个是确保一个特定的用例。例如,从网页创建标签将实现我期望的功能。为此,我使用Visual studio 2012附带的sql server,每次测试后,我都会删除数据库并重新开始


在我的例子中,我会说集成测试比单元测试重要得多。这是因为我的应用程序没有那么多逻辑,而是以不同的方式显示数据库中的数据

您最初的测试还没有完成,仅此而已。最后的测试总是要处理新用户被持久化的事实

TDD没有规定您应该创建的测试类型。您必须事先选择是单元测试还是某种集成测试。如果是单元测试,那么模拟的使用实际上是不可避免的(除非被测试的单元没有可隔离的依赖项)。如果是集成测试,那么在测试中必须考虑实际的数据库访问(在本例中)


这两种测试都是正确的。通常的看法是,创建一个更大的单元测试套件,单独测试单元,而一个单独但较小的测试套件则执行整个用例场景。

实际上,您需要模拟来进行单元测试。单元测试是为了测试尽可能最小的单元(对于某些人来说是类或方法)。如果不模仿其他类,就不会是真正的单元测试。如果你不模仿任何东西(并测试类之间的交互),那将是集成测试。是的,我意识到了这一点,我正试图将其应用于TDD,所以我不知道应该从什么时候开始