是否更喜欢在Mockito中对每个"when"调用进行"验证"调用?



在编写测试用例时,通常的模式是setup>execute祝辞verify。这将导致单元测试如下所示:

@Test
void testSomething() {
// Setup
when(someMock.someMethod()).thenReturn("someValue");

// Execute (the doSomething implementation would invoke someMock.someMethod)
testee.doSomething();

// Verify
verify(someMock, times(1)).someMethod();
}

我的问题是,考虑到call何时会引发UnnecessaryStubbingException异常,是否有必要包括verify调用?

这个问题只适用于times1的情况,因为没有UnnecessaryStubbingException只意味着someMethod被调用了一次,并且使用了正确的参数,并且可能存在您想要验证someMethod被调用never的情况。如果没有验证,测试将看起来像这样,并实现相同的检查:

@Test
void testSomething() {
// Setup
when(someMock.someMethod()).thenReturn("someValue");

// Execute (the doSomething implementation would invoke someMock.someMethod)
testee.doSomething();
}

编辑:一个朋友指出verifyNoMoreInteractions依赖于你有verify调用,所以我想这是重要的考虑。

编辑2:我已经更改了"必需品"。";preferred"因为我更感兴趣的是每种方法的优缺点,而不是技术要求。

提前感谢!

这不是必需的,正如您所提到的—技术上测试验证了这种行为。所以选择应该基于你的团队的偏好和专业知识。我个人认为有明确的验证步骤使您的测试更易于阅读和维护。几个原因:

  • 你可以有更多的when调用,不相关的验证逻辑,这将"隐藏";测试意图,例如
@Test
void testSomething() {
// Setup
when(someMock.someMethod()).thenReturn("someValue");
when(someMock2.someMethod2()).thenReturn("someValue2");
when(someMock3.someMethod3()).thenReturn("someValue3");

// Execute (the doSomething implementation 
// would invoke someMock.someMethod)
testee.doSomething();
// code reviewer - "hm? what do we really test here?"
}
  • 从API的角度来看,UnnecessaryStubbingExceptionwhen中抛出异常并不明显——这可能会给偶尔错过这一事实的代码读者带来困惑。有了verify,几乎所有开发人员都可以清楚地了解测试的意图,甚至来自其他技术堆栈
  • 一些开发人员可能来自早期的Mockito版本,其中UnnecessaryStubbingException的抛出不是这种情况
  • UnnecessaryStubbingException仅在Mockito处于严格模式时引发。如果将此设置更改为宽大,那么您将不再能够依赖此异常被引发。
  • 您可以创建不包含verify呼叫的场景,后续verifyNoMoreInteractions呼叫将失败。

如果您已经意识到您的代码段将抛出异常,那么最好有一个覆盖它的测试用例,就像下面

@Test(expected = UnnecessaryStubbingException.class)

没有任何断言或验证语句的测试用例(您已经跳过验证的那个)在其中没有任何意义。当方法具有void返回类型时,进行验证检查是一种很好的方法。

不需要添加Verify为每一次打电话给Mockito。每个测试用例本质上应该是确定性的。

要回答你的问题,在这种特殊情况下,首选的方法是使用verifyNoMoreInteractionsverify(somemock, never()).someMethod()

没有必要总是需要验证。您可以使用断言也但是,一个测试用例必须有它们中的一个.

例如。如果你确定某个方法将抛出异常。


@Test(expected = HeyIAmException.class)
void testSomething() {
classUnderTest.someMethodWhichThrowsException();
}

@Test
void testSomething() {
when(someMock.someMethod()).thenReturn("someValue");
HeyIAmException exception = assertThrows(HeyIAmException.class, () ->
classUnderTest.someMethodWhichThrowsException()
);

assertEquals(exception.getCode(),rightCode);
}

在你的方法中,除了Udalmik的回答之外,我还有以下几行要添加。

  • 我们永远不会知道哪个stub方法引起了异常,因为someMethod中的任何一个都可能抛出异常。
  • 测试的意图不是很明确。