在 Mockito 中重用模拟行为/最佳实践? [英] Reusing mock behavior / best practice in Mockito?
问题描述
我的背景是,我非常年轻,一般没有太多的测试经验,以前从未使用过模拟框架.
I'll preface this with the background that I am very green and don't have much experience with testing in general, and have never used a mocking framework before.
我正在为访问许多不同 Web 服务的代码编写单元测试,我对此进行了嘲讽.我的许多测试验证了一个调用的结果,其中除了对 ServiceX 的调用之外,我的所有服务调用都成功.我的第一反应是为@Before 块中的所有模拟设置happy-path 行为,然后为每个测试修改模拟行为.
I am writing unit tests for code that hits a lot of different web services, which I have mocked. Many of my tests verify the result of a call where all of my service calls are successful except a call to ServiceX. My first instinct was to set up happy-path behavior for all mocks in a @Before block and then modify the mock behavior for each test.
@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);
...
这使得每个测试用例都简洁,并且很容易看到正在测试的内容,因为我只指定了偏离规范的行为.
which makes each test case succinct, and it is easy to see what is being tested, since I only specify the behavior which deviates from the norm.
但我怀疑这不是 Mockito 希望我设置模拟行为的方式,因为当我试图验证 ServiceB 中的失败意味着 ServiceC 永远不会被命中时,我意识到我对 when(serviceC@Before 中的 .doSomething())
算作对 serviceC 的调用.也就是说,我的 verifyZeroInteractions(serviceC)
总是失败,因为我调用了 when(serviceC.doSomething()).thenReturn(true)
,即使测试用例从未触及 serviceC否则.
But I suspect that this is not how Mockito wants me to set up mock behaviors, because when I tried to verify that a failure in ServiceB means that ServiceC is never hit, I realized that my calls to when(serviceC.doSomething())
in the @Before counted as invocations on serviceC. That is, my verifyZeroInteractions(serviceC)
always failed because I had called when(serviceC.doSomething()).thenReturn(true)
, even when the test case never touched serviceC otherwise.
那么最佳实践是什么?即使我会在所有地方重复几乎相同的 5 行,我是否最好在每次测试中为每个模拟明确设置行为?
So what is the best practice? Am I better off just explicitly setting up the behavior for every mock in every test, even though I'd be repeating nearly the same 5 lines all over the place?
推荐答案
when(serviceC.doSomething()) in the @Before counted as invocations on serviceC
我怀疑 when
构造是否被视为调用,因为那只是存根.
您能否仔细检查您的代码以查看是否从您的 @Test
I doubt that the when
construct is treated as an invocation because that is just stubbing.
Can you double check your code to see whether serviceC.doSomething
is called from within your @Test
关于最佳实践,我认为您应该只将所有测试用例常见的存根行为移动到 @Before
Regarding the best practice, I think you should only move in stubbing behaviour which is common for all test cases into @Before
除了代码的外观之外,我认为您可以尝试重构为责任链
模式和这个应该可以帮助您编写测试代码.
As an aside from the way your code is looking I think you can try refactoring into Chain of Responsibility
pattern and this should help you in coding the test code.
这篇关于在 Mockito 中重用模拟行为/最佳实践?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!