java - Mockito:验证是否执行了任何线程中指定的方法?
问题描述
我有一个类似以下的方法:
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
由于多线程,您的测试验证在方法之前运行。
那时测试说“想要但未调用”是正确的(测试代码运行,检查生产方法是否已经运行,它没有......然后在后台运行生产代码(为时已晚))。
理想情况下,您应该将线程控制与应用程序中的逻辑分开。包装Thread
在 a 中ThreadFactory
,对于真正的代码,您可以传递一个实际的线程,对于测试代码,您可以传递一个立即运行代码的对象(在同一个线程上)。
或者(不推荐)你破解你的测试(这将帮助你理解):
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 秒即可完成执行?
这并不理想,就像我最初所说的那样,您希望将线程从该方法中拉出,将某种类型的工厂传递给类并在测试中传递一个 Fake 对象。(从而避免尝试测试多线程代码。)
推荐阅读
- vba - CorelDraw VBA 在 CQL 中使用变量
- java - 如何在 Spring Boot 的 YML 文件中创建条件属性?
- c++ - 包含 minwindef.h 后的 BOOL 重新定义
- python - 按组规范化pyspark数据帧
- excel - 没有标签或属性的子嵌套提取数据
- types - int 数据类型的大小在 32 位架构机器上是否可能为 64 位?
- .net - 在 MSbuild 不工作的情况下为 Teamcity 构建工件,希望将其传递给 powershell 变量以实现部署功能
- android - 如何改进 Android Eclaire 上的 WebView?
- apache - 不带www直接重定向
- java - 如何将 java.net.MulticastSocket 绑定到 localhost