Mockito void doAnswer 正确用法和目的

Coo*_*zza 1 java unit-testing mockito

今天我了解了 Mockito,在玩弄它时我发现了一些我不明白的东西。

假设我想测试以下代码:

    public void stop(boolean showMessage) {
    if(executor != null && !executor.isShutdown() && this.isRunning) {
        if(showMessage) { 
            View.getSingleton().showMessageDialog(Constant.messages.getString("sessionchecker.stopmessage"));
        }

        executor.shutdownNow();
        executor = null;
        extension.getCountdownTimer().stopCountdown();

        this.isRunning = false;
        this.usersReady.clear();
    }
}
Run Code Online (Sandbox Code Playgroud)

由于 stop 方法是无效的,我需要调用doAnswer(如果我理解正确的话)。所以我尝试了以下方法:

    @Test
public void testStopIsRunningFalse() {
    Mockito.when(controller.isRunning()).thenReturn(true); // Mock a running service
    Mockito.doAnswer(new Answer<Void>() {

        @Override
        public Void answer(InvocationOnMock invocation) throws Throwable {
            if(controller.isRunning()) {
                // Normally would actually shut down service
                Mockito.when(controller.isRunning()).thenReturn(false); // Service should stop
            }
            return null;
        }
    }).when(controller).stop(false);
    controller.stop(false);
    boolean expected = false;
    assertEquals(expected, controller.isRunning());
}
Run Code Online (Sandbox Code Playgroud)

然而,我不明白这样的测试的目的是什么。为什么我要这样测试它,因为这永远不会失败(参数isRunning正在按照我的预期设置)。基本上我只需要测试的状态的某些字段的(isRunningexecutor例如)。但是,这些字段没有公共 getter 或 setter。

因此,我想我误解了deAnswer. 有人可以帮我吗?

Kev*_*ker 5

如果我理解您的代码示例,那么您似乎是在模拟要测试的对象,这在 99.9% 的情况下都是不允许的。您通常只想模拟您正在测试的课程的直接合作者。协作者包括诸如注入的服务(或其他注入的字段)和您正在测试的方法的参数之类的东西——基本上是在您调用被测试的方法之前代表被测类的初始状态的任何东西。