我正在将一些测试移到较新的Mockito版本,当涉及到@ParameterizedTest
测试和Mockito的UnnecessaryStubbingsException
时,我遇到了障碍。
问题是,所讨论的测试有时需要模拟一个服务,这取决于测试的参数。对于某些参数,代码将不会执行到调用模拟服务的行,而对于其他参数,代码将执行到调用模拟服务的行。
这会导致Mockito在未使用mock的情况下抛出UnnecessaryStubbingsException
。我不能删除存根,因为这样的话,对于代码实际执行到需要模拟服务的点的参数,测试将失败。
为了举例说明,假设我有一个正在测试的虚拟方法:
public boolean process(String flag) {
if (Objects.equals(flag, "flag1")) {
throw new IllegalArgumentException("Oh no, exception!");
}
boolean result = someService.execute(flag);
if (result) {
throw new IllegalArgumentException("Oh no, exception!");
}
return result;
}
然后进行参数化测试以检查多个标志:
@ParameterizedTest
@MethodSource("getFlags")
void shouldTestIfFlagWorks(String someFlag) {
// Given
Mockito.doReturn(true).when(someService).execute(someFlag);
// When
Throwable thrown = Assertions.catchThrowable(() -> serviceUnderTest.process(someFlag));
// Then
Assertions.assertThat(thrown).hasMessage("Oh no, exception!");
}
private static Stream<Arguments> getFlags() {
return Stream.of(
Arguments.of("flag1"),
Arguments.of("flag2")
);
}
这个例子有点做作,但是使用UnnecessaryStubbingsException
会失败,因为测试运行的第一个参数不需要mock。如果我删除存根,使用第一个参数的测试将工作,而使用下一个参数的第二次运行将失败。
有什么办法可以解决这个问题吗?我知道可以解决这个问题的一个选择是使用Mockito.lenient()
。另一个选择是重构并将需要mock的参数移动到单独的测试中。
我很好奇是否有任何不同的/更好的方法,或者我在这里错过了什么。
2条答案
按热度按时间o7jaxewo1#
使用:
和
当测试为:
试跑鞋号
UnnecessaryStubbingsException
:你自己试试:
它使用这些依赖项:
编辑:我刚刚还检查了
Java8
和Java11
以及testImplementation group: 'org.mockito', name: 'mockito-all', version: '2.0.2-beta'
,但每次都检查了junit5
:同样的结果,仍然没有UnnecessaryStubbingsException
出现。nvbavucw2#
我不认为你漏掉了什么。你说的都对。
我的理解是,
UnnecessaryStubbingsException
是Mockito告诉你的方式:嘿,你为你的测试定义了一些没有必要的模拟行为,因为我们从来没有达到那个点。你最好删除它,以保持你的测试干净。
如果你对mock行为的不必要定义没有意见,因为参数化测试的一些参数会导致mock被调用,而其他参数则不会,那么 * lenant * 将是一条可行的路。所以,如果你像这样定义mock,异常就会消失:
所以我个人的回答是:有这个异常是很好的,因为它可以让我们再次考虑代码、测试和异常,然后确定这正是我想要做的,并将模拟设置为宽松。