8

我正在使用依赖注入为我正在测试的类之外的代码提供模拟。我发现自己一遍又一遍地编写了很多相同的代码,因为我需要模拟在我想要测试的方法中使用的 AuthProvider、ConfigurationManager 等。该方法包含分支(if-then-else),因此我有多个测试来测试该方法的所有执行路径。我多次实例化每个模拟(在每种测试方法中一次),但我想知道这是否是错误的方法?此外,我对模拟和预设响应提出了期望,这些响应显然主要是复制粘贴,因为在每个方法中都会调用诸如 AuthProvider.Authenticate() 之类的调用

在每种方法中,我都设置了一个模拟存储库,并在每种方法结束时验证了模拟存储库。我是否应该有某种工厂来创建这些模拟以及设置它们的期望和返回值,如果是这样,如何?

为了实现模拟,我正在使用 RhinoMocks。

4

5 回答 5

5

“多次实例化每个模拟”不是问题。对象是免费的。

请确保您没有多次定义模拟类。上课很贵。

此外,您在 TestCase 中有一个“setUp”方法,它允许您创建一个供所有测试使用的夹具。是的,它为每个测试重建。不,这不是问题,除非它非常缓慢。

于 2009-01-06T16:28:52.317 回答
2

假设您使用的是 NUnit,您可以为您的 Mocks 使用实例变量并在 Setup/Teardown 中重置它们。如果你看到重复的模式,那么就按照你对生产代码所做的事情:重构并提取帮助方法来表达你想要实现的目标(如果根本没有共性,那么生产代码的设计就有问题)。

如果设置中存在重大差异,请考虑为您的生产类编写多个测试类。

最后,想想你的生产类是否太忙了,一些行为应该被提取到一个辅助对象中。

听测试!

于 2009-05-21T17:02:59.937 回答
1

这是我的看法..

在这种情况下我不会使用mock ...我会使用工厂方法来返回类的假实现,并使用依赖注入来使用这个实现。这样你可以避免重复并且可以再次重用这个实现n ...再次,这个工厂实现需要正确重构,即没有重复..

模拟,我想应该在您测试一些动态行为时使用......当我对 SUT 执行某些操作时,是否调用了子系统中的方法......然后调用 verify() 来验证此行为。 .. 还有一篇关于 Martin Folwer bliki Mock Aren't Stubs的好文章

于 2009-01-06T17:55:12.843 回答
0

您可能希望考虑使用 AAA 测试风格,以便使用通用设置进行多个测试。这是一个体面的例子。

于 2009-01-06T17:10:18.533 回答
0

如果您不对模拟调用设置期望,像 EasyMock 这样的记录和重放框架会失败。但是像 Mockito 这样的框架只是简单地记录所有调用并让您只验证重要的调用。因此,您不必对所有测试中的所有方法都设定期望。

回到您在每个测试方法中实例化 Mocks 的问题,有比使用 setUp() 方法更好的方法。Mockito 提供了一个 @Mock 注释。所以你声明你的变量(作为字段),如:@Mock Repository repositoryMock

只需在 setUp() 中调用 initMocks()。声明的所有模拟对象在您的测试中自动可用,而无需显式创建模拟。

于 2009-01-06T18:02:02.160 回答