【发布时间】:2017-07-17 22:12:16
【问题描述】:
我有以下代码用于对 Callable 参数执行操作的方法:
public static <T> T queryWithRetry(Callable<T> query, int maxTries, int retryIntervalInMilliseconds) throws MongoServiceException, InterruptedException {
int tries = MAX_TRIES;
while (tries-- > 0) {
try {
return query.call();
} catch (TimeoutException e) {
LOGGER.debug(String.format("Query timed out. Retrying attempt %d/%d", MAX_TRIES - tries, MAX_TRIES));
Thread.sleep(RETRY_INTERVAL_IN_MILLISECONDS);
continue;
}
throw new RandomException();
}
我正在使用 Mockito 尝试验证 query.call() 行在抛出 RandomException 之前被尝试了 MAX_TRIES 的次数。我尝试使用以下测试代码来做到这一点:
public class CallableQueryTest {
private static final int MAX_TRIES = 3;
private static final int RETRY_INTERVAL_IN_MILLISECONDS = 100;
@Mock
private Callable<Document> mockCallable;
@Rule
public ExpectedException thrown = ExpectedException.none();
@Before
public void setUp() throws Exception {
mockCallable = Mockito.mock(Callable.class);
}
@Test
public void testQueryConfigThrowsRandomExceptionOnTimeout() throws Exception {
Mockito.when(mockCallable.call()).thenThrow(new TimeoutException("timeout"));
thrown.expect(RandomException.class);
Mockito.verify(mockCallable, Mockito.atMost(1)).call();
MongoQueryUtils.queryWithRetry(mockCallable, MAX_TRIES, RETRY_INTERVAL_IN_MILLISECONDS);
}
}
Mockito 代码成功测试了该方法抛出了 RandomException,但错误地表示测试通过了。
这个测试应该失败,因为我写道 Mockito 应该验证 mockCallable.call() 最多执行一次,但据我了解,它被称为 MAX_TRIES 次(设置为 3)。
有人可以解释这种行为并就如何正确测试mockCallable.call() 被调用的次数提供建议吗?
【问题讨论】:
-
不相关:我发现您对
queryWithRetry()声明的 方法参数 使用全部大写的事实令人困惑。您对 CONSTANTS 使用全部大写 - 但赋予该方法的参数的整个想法是:它可能在每次被调用时都不同。这只是一个正常的参数。除此之外:当您使用 Java8 时,只需 not 通过它的 name 说“这个值以毫秒为单位” - 使用新的 Duration 类来简单地传递可以变成毫秒! -
但是这些变量没有在方法
queryWithRetry()中声明?它们是大写的,因为它们是常量,定义在类的顶部。它们在整个测试文件中都使用过,但我只对代码中的第一个测试用例进行了采样。持续时间提示很有帮助,谢谢! -
queryWithRetry()的签名(在我看来)几乎无法阅读。我知道有些人喜欢把 final 放在任何地方,但我发现它对方法参数没有帮助。如前所述:调用 foo(BAR_CONST) 很好,但方法签名应该不读取void foo(Bar BAR_CONST)- 因为您不知道如何调用该方法。大写用于常量,参数不是常量。所有恕我直言。 -
我猜这是混淆的一部分:MAX_TRIES within 该方法指向该方法参数; 不是那个常数。如果这两个东西都在同一个文件中,则本地 MAX_TRIES 甚至会 shadow 外部常量。阴影是非常谨慎的事情!
-
哦,我明白你的意思了。我最初并不了解您,因为我已经更新了本地代码以反映这一点(并且忘记编辑堆栈溢出)!我的推理方式和你一样:)
标签: java unit-testing mocking mockito callable