java - 如何在 JMockit 中正确模拟私有 ExecutorService 的提交方法
问题描述
我有一个包含私有 ExecutorService 实例的类。在类中,我有一个运行提交方法并捕获 RejectedExecutionException 的方法。但是,我在模拟 ExecutorService 实例以引发异常以完成测试覆盖时遇到了麻烦。我正在使用 JMockit 1.45。
我已经浏览过 JMockit 教程和其他网站;无论我使用@Mocked、@Capturing,还是创建一个新的假类,它似乎都不起作用。
// Implemented Class:
public class TaskRegister {
private ExecutorService executor;
public TaskRegister() {
this.executor = Executors.newFixedThreadPool(5);
}
public void executeTask(Runnable task) {
try {
this.executor.submit(task);
} catch (RejectedExecutionException e) {
System.out.println(e.getMessage);
}
}
}
// Unit Test Class:
public class TestTaskRegister {
@Tested
private TaskRegister tested;
private static int counter;
@Test // this works
public void runNormalTask() throws InterruptedException {
counter = 0;
Runnable mockTask = new Runnable() {
counter++;
}
tested.executeTask(mockTask);
Thread.sleep(100); // Allow executor to finish other thread.
assertEquals(1, counter);
}
@Test // this doesn't work, will have missing invocation error.
public void throwsError (@Capturing ExecutorService executor) throws InterruptedException {
counter = 0;
// somehow the tested class still runs the actual executor
// and not the mocked one.
new Expectations() {{
executor.submit((Runnable) any);
result = new RejectedExecutionException();
}};
Runnable mockTask = new Runnable() {
// some task
}
tested.executeTask(mockTask);
Thread.sleep(100);
assertEquals(0, counter);
}
}
我希望@Capturing 拦截真正的执行器实现并在调用 executor.submit 时抛出异常,但它没有这样做。
解决方案
Mocking by@Capturing
可能很昂贵,并且在某些情况下可能会导致意外结果,因此(当前)所有java.*
类都被排除在外。所以,java.util.concurrent.ThreadPoolExecutor
在这个测试中不会被嘲笑(可以用@Mocked
)。
在实践中,RejectedExecutionException
异常永远不会发生(ThreadPoolExecutor
至少不会发生 - 可能只有 a ForkJoinPool
)。所以,这个测试是不值得的。实际上,由于该异常是 aRuntimeException
您可以简单地catch
完全删除该块。
这是(滥用)使用模拟库时发生的坏事之一:人们有时使用它们来测试不可能的情况,因此编写无用的测试。
推荐阅读
- xcode - ios 的 Ionic 构建失败。InAppBrowser 抛出错误
- html - 我的导航栏内容相互合并
- python-3.x - 从日期时间对象解析日期,然后从字典列表中删除重复项
- sql - 在 Oracle 中将 LONG 转换为时间戳
- javascript - 使用ffmpeg循环编辑视频时出错
- haskell - Haskell 错误 - 无法将类型 `[Int] -> String' 与 `[Char]' 匹配;预期类型:字符串;实际类型:[Int] -> String
- r - 在 R 语言中基于单词序列查找两个字符串之间的匹配
- django - ManagementForm 数据丢失或被篡改。缺少字段:servicesprice_set-TOTAL_FORMS
- android - Android在Webview中仅打开相机选项
- javascript - React:当多个文件名是 index.{js,jsx} 时,使调试更容易的建议?