Mockito,doNothing()的用法When()

d5vmydt9  于 2022-11-08  发布在  其他
关注(0)|答案(3)|浏览(731)

我是Mockito的新手,我已经看过这个例子,但是当它在方法的第一行调用doNothing()时,有一个步骤我不理解:

@Test(expected = RuntimeException.class)
public void testConsecutiveCalls() throws Exception(){
  doNothing().doThrow(Exception.class).when(b).voidMethod();
  a.usesVoidMethod()
  verify(b).voidMethod();
  a.usesVoidMethod()
}

我确实理解,当第一次调用voidMehtod()时,它什么也不返回,而在第二次调用时,它会给出一个异常。
但是,如果我们删除了doNothing.doThrow(Exception.class).when(b).voidMethod();,测试是否仍然有效,并将测试我们要测试的内容,即该方法在第二次抛出异常?

vyu0f0g1

vyu0f0g11#

以下是几个要点,编号仅为便于参考:
1.mock 的默认行为是每次返回一个适当的伪值,通常是零、null或空字符串。spy的默认行为是调用spy的实际实现。当然,通过@MockMockito.mock的参数,可以使用任意Answer或Mockito的standardadditional答案。
1.当多个动作作为一个链的一部分被给出时,Mockito将按顺序做每个动作,并永远重复最后的动作。

// calls to foo.bar() return 1, 2, 3, 3, 3...
doReturn(1).thenReturn(2, 3).when(foo).bar();

请注意,这是在同一个链中;最近定义的匹配链获胜,因此单独的语句不会有相同的效果。

doReturn(1).thenReturn(2).when(foo).baz();
doReturn(3).thenReturn(4).when(foo).baz();
// calls return 3, 4, 4, 4... because the first chain is entirely overridden.

1.然后,doNothing从 * 覆盖默认行为 * 或 * 在链中设置动作 * 中获得其大部分值。
因此,测试 * 尝试 * 做的是第一次对doNothing进行验证,以确保验证成功,然后第二次对doThrow进行验证,以满足预期的异常。因为Mockito's errors subclass Error and not Exception,删除doNothing仍然会通过在第一次调用a.usesVoidMethod()时抛出异常来使测试通过,您可以在测试本身中看到doNothing--一个更健壮的测试可能如下所示:

@Test
public void testConsecutiveCalls() throws Exception(){
  doNothing().doThrow(SomeKnownException.class).when(b).voidMethod();
  a.usesVoidMethod();
  verify(b).voidMethod();
  try {
    a.usesVoidMethod();
    fail();
  } catch (SomeKnownException expected) { /* OK */ }
}
1wnzp6jl

1wnzp6jl2#

doNothing方法不会改变mocked' method, but the declaration of the doThrow does. If you have a spy and don't want a method to be executed, then doNothing '不会改变它的行为。

e4yzc0pl

e4yzc0pl3#

这个测试是个糟糕的测试,因为(1)它没有多大意义,(2)它测试的是两个不同的东西:

  1. a.usesVoidMethod()调用b.voidMethod()
    1.当依赖项b抛出Exception时,被测对象a抛出RuntimeException
    (c),它的命名不正确,它独立地测试上面两个东西,它们是连续调用的事实是不相关的。
    如果您删除了这个测试方法的第一行,那么您就删除了被模拟的b的行为。测试将会失败,因为在默认情况下,对模拟的void方法调用不会执行任何操作;即将不存在来自x1M8 N1 x的x1M7 N1 x,且因此不存在来自x1M10 N1 x的x1M9 N1 x。
    你是对的,如果a被编写成在被调用两次时抛出RuntimeException,那么就不需要对b进行嘲弄,但这比现在更不合理。

相关问题