Mockito:验证是否执行了任何线程中指定的方法?

Mockito: Verify if a method specified in any thread got executed?

我有如下方法:

void enact(@NonNull final Request request) {
        XInput input = this.xBuilder.buildInputPayload(request);
        final Thread componentThread = new Thread(()->this.component.runJob(input));
        componentThread.start();
        return;    
}

void testVTService_Success() {
        when(xBuilder.buildInputPayload(any(Request.class))).thenReturn(inputPayloadWithAllArguments);
        activity.enact(TestConstants.request);
        verify(component, times(1)). runJob(any(XInput.class)); //Verification
    }

在验证 component.runJob() 方法正在执行后,它抛出一个错误,指出 Wanted but not invoked: component.runJob() Actually, there were zero interactions with this mock.

我该如何解决这个问题?并验证线程是否正在启动并执行 runJob 方法?

您的测试在一个线程上 运行,您的测试代码运行一个新线程。

这意味着由于多线程,您的测试验证在 runJob 方法之前运行。

此时测试说“需要但未调用”是正确的(测试代码运行,检查生产方法是否有运行,它没有...a然后在后台制作代码运行(来不及了))。

理想情况下,您应该将线程控制与应用程序中的逻辑分开。将 Thread 包装在 ThreadFactory 中,对于真实代码,您可以传递一个实际的线程,对于测试代码,您可以传递一个立即运行代码的对象(在同一线程上)。

或者(不推荐)你 hack 你的测试(这将帮助你理解):

void testVTService_Success() {
    when(xBuilder.buildInputPayload(any(Request.class)))
    .thenReturn(inputPayloadWithAllArguments);

    activity.enact(TestConstants.request);

    try { Thread.sleep(TimeUnit.SECONDS.toMillis(10)); } catch (Exception e) { assertTrue(false); }

    verify(component, times(1)). runJob(any(XInput.class)); 
}

现在您的测试总是需要 10 秒,但希望生产代码不需要 10 秒来完成执行?

这并不理想,正如我最初所说的那样,您可能希望将线程从该方法中拉出,将某种类型的工厂传递给 class 并在测试中传递一个 Fake 对象。 (从而避免尝试测试多线程代码。)