在 Mockito 中重用模拟行为/最佳实践?



我将在前面加上一个背景,我非常绿色,一般没有太多的测试经验,并且以前从未使用过模拟框架。

我正在为命中很多不同 Web 服务的代码编写单元测试,我已经嘲笑过这些服务。 我的许多测试都验证了呼叫的结果,其中除对 ServiceX 的调用外,我的所有服务调用都成功。 我的第一直觉是为@Before块中的所有模拟设置快乐路径行为,然后修改每个测试的模拟行为。

@Before
public void init(){
when(serviceA.doSomething()).thenReturn(true);
when(serviceB.doSomething()).thenReturn(true);
when(serviceC.doSomething()).thenReturn(true);
when(serviceD.doSomething()).thenReturn(true);
when(serviceE.doSomething()).thenReturn(true);
}
@Test
public void testDoBusinessSuccess(){
String result = businessLogic.doBusiness();
assertThat(result, is("success"));
}
@Test
public void testDoBusinessFailureWhenServiceAFails(){
when(serviceA.doSomething()).thenReturn(false);
String result = businessLogic.doBusiness();
assertThat(result, is("service A is down!"));
}
@Test
public void testDoBusinessFailureWhenServiceBFails(){
when(serviceB.doSomething()).thenReturn(false);
...

这使得每个测试用例都简洁,并且很容易看到正在测试的内容,因为我只指定偏离规范的行为。

但我怀疑这不是 Mockito 希望我设置模拟行为的方式,因为当我尝试验证 ServiceB 中的失败是否意味着 ServiceC 永远不会被命中时,我意识到我在 @Before 中对when(serviceC.doSomething())的调用算作对 serviceC 的调用。 也就是说,我的verifyZeroInteractions(serviceC)总是失败,因为我调用了when(serviceC.doSomething()).thenReturn(true),即使测试用例从未接触过serviceC。

那么最佳实践是什么? 我是否最好只是明确地为每个测试中的每个模拟设置行为,即使我会到处重复几乎相同的 5 行?

when(serviceC.doSomething()) in the @Before counted as invocations on serviceC

我怀疑when结构是否被视为调用,因为这只是存根。
您能否仔细检查您的代码以查看是否从您的@Test中调用serviceC.doSomething

关于最佳实践,我认为您应该只将所有测试用例常见的存根行为移动到@Before

除了代码的外观之外,我认为您可以尝试重构为Chain of Responsibility模式,应该可以帮助您编写测试代码。

这不是特定于模拟的,但只有每个测试通用的代码才应该进入@Before,因为它在每个 junit 测试之前都会执行。

因此,如果你想要特定于测试的行为,那么所有嘲笑的东西都应该在这些测试中。

如果您有多个测试共有的行为,则可以将其提取到仅由需要该行为的测试调用的方法中。

verify计数的调用是测试方法本身中的调用。 将 each 方法中的调用更改为如下所示。

doReturn(false).when(serviceA).doSomething();

这将与您正在执行的存根相同的效果;但它不会被视为出于验证目的而调用doSomething

相关内容

  • 没有找到相关文章