在 Mockito 中重用模拟行为/最佳实践? [英] Reusing mock behavior / best practice in Mockito?

查看:45
本文介绍了在 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆