我将以我非常新手并且没有太多一般测试经验并且之前从未使用过模拟框架的背景作为序言。
我正在为命中许多不同网络服务的代码编写单元测试,我已经 mock 过这些服务。我的许多测试都会验证调用的结果,其中我的所有服务调用都成功,但对 ServiceX 的调用除外。我的第一直觉是为 @Before block 中的所有模拟设置快乐路径行为,然后为每个测试修改模拟行为。
@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 永远不会被命中时,我意识到我对 when(serviceC @Before 中的 .doSomething())
算作对 serviceC 的调用。也就是说,我的 verifyZeroInteractions(serviceC)
总是失败,因为我调用了 when(serviceC.doSomething()).thenReturn(true)
,即使测试用例从未接触过 serviceC否则。
那么最佳做法是什么?我是否最好只是明确地为每个测试中的每个模拟设置行为,即使我会在所有地方重复几乎相同的 5 行?
最佳答案
when(serviceC.doSomething()) in the @Before counted as invocations on serviceC
我怀疑 when
构造是否被视为调用,因为那只是 stub 。
您能否仔细检查您的代码以查看是否从您的 @Test
serviceC.doSomething
关于最佳实践,我认为您应该只将对所有测试用例都很常见的 stub 行为移入@Before
除了代码的外观之外,我认为您可以尝试重构为 Chain of Responsibility
模式和 this 应该可以帮助您编写测试代码。
关于java - 在 Mockito 中重用模拟行为/最佳实践?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13061581/