在编写测试用例时,通常的模式是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
调用?
这个问题只适用于times
是1
的情况,因为没有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
调用,所以我想这是重要的考虑。
提前感谢!
这不是必需的,正如您所提到的—技术上测试验证了这种行为。所以选择应该基于你的团队的偏好和专业知识。我个人认为有明确的验证步骤使您的测试更易于阅读和维护。几个原因:
- 你可以有更多的
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的角度来看,
UnnecessaryStubbingException
在when
中抛出异常并不明显——这可能会给偶尔错过这一事实的代码读者带来困惑。有了verify
,几乎所有开发人员都可以清楚地了解测试的意图,甚至来自其他技术堆栈 - 一些开发人员可能来自早期的Mockito版本,其中
UnnecessaryStubbingException
的抛出不是这种情况 UnnecessaryStubbingException
仅在Mockito处于严格模式时引发。如果将此设置更改为宽大,那么您将不再能够依赖此异常被引发。- 您可以创建不包含
verify
呼叫的场景,后续verifyNoMoreInteractions
呼叫将失败。
如果您已经意识到您的代码段将抛出异常,那么最好有一个覆盖它的测试用例,就像下面
@Test(expected = UnnecessaryStubbingException.class)
没有任何断言或验证语句的测试用例(您已经跳过验证的那个)在其中没有任何意义。当方法具有void返回类型时,进行验证检查是一种很好的方法。
不需要添加Verify为每一次打电话给Mockito。每个测试用例本质上应该是确定性的。
要回答你的问题,在这种特殊情况下,首选的方法是使用verifyNoMoreInteractions
或verify(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
中的任何一个都可能抛出异常。 - 测试的意图不是很明确。