sam*_*uri 8 java unit-testing executorservice
如何对执行程序服务中运行的代码进行单元测试?在我的情况下,
public void test() {
Runnable R = new Runnable() {
@Override
public void run() {
executeTask1();
executeTask2();
}
};
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(R);
}
Run Code Online (Sandbox Code Playgroud)
当我进行单元测试时,我想做一些方法执行的验证.
我正在执行器服务中执行此操作,因为它进行了一些网络操作.
在我的单元测试中,我不得不等到这个方法完成执行.有没有更好的方法可以做到这一点,而不是等待Thread.sleep(500).
单元测试代码段:
@Test
public void testingTask() {
mTestObject.test();
final long threadSleepTime = 10000L;
Thread.sleep(threadSleepTime);
verify(abc, times(2))
.acquireClient(a, b, c);
verify(abd, times(1)).addCallback(callback);
}
Run Code Online (Sandbox Code Playgroud)
注意:我将一个执行程序服务对象传递给此构造函数类.我想知道是否有一种好的测试方法而不是等待睡眠时间.
cla*_*dio 12
您也可以自己实现一个ExecutorService,它将在同一个线程中运行该任务.例如:
public class CurrentThreadExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以继承AbstractExecutorService并使用这个实现.
如果您正在使用Guava,另一个简单的方法是使用MoreExecutors.newDirectExecutorService(),因为它可以完成同样的事情而无需您自己创建一个.
Google Guava 提供了一个很棒的类MoreExecutors,它在测试通过JUnitExecutor或ExecutorService在并行线程中运行的代码时帮助了我。它允许您创建Executor仅在同一线程中运行所有内容的实例,本质上是作为真实Executor. 问题是当事情在 JUnit 不知道的其他线程中运行时,这些ExecutorsfromMoreExecutors使一切更容易测试,因为它实际上不是在另一个线程中并行的。
请参阅MoreExecutors文档https://google.github.io/guava/releases/19.0/api/docs/com/google/common/util/concurrent/MoreExecutors.html
你可以修改你的类构造函数,或者添加一个你只在测试中使用的新构造函数,这样你就可以提供自己的Executor或ExecutorService. 然后传入MoreExecutors.
因此,在测试文件中,您将使用以下命令创建模拟执行程序 MoreExecutors
ExecutorService mockExecutor = MoreExecutors.newDirectExecutorService();
// or if you're using Executor instead of ExecutorService you can do MoreExecutors.newDirectExecutor()
MyService myService = new MyService(mockExecutor);
Run Code Online (Sandbox Code Playgroud)
然后在你的类中,如果构造函数中没有提供它,你只创建一个真正的 Executor
public MyService() {}
ExecutorService threadPool;
public MyService(ExecutorService threadPool) {
this.threadPool = threadPool;
}
public void someMethodToTest() {
if (this.threadPool == null) {
// if you didn't provide the executor via constructor in the unit test,
// it will create a real one
threadPool = Executors.newFixedThreadPool(3);
}
threadPool.execute(...etc etc)
threadPool.shutdown()
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用 executorService.submit(R) 返回的 Future 实例。
来自文档:
提交一个 Runnable 任务来执行并返回一个表示该任务的 Future。Future 的 get 方法在成功完成后将返回 null。
例子:
@Test
void test() throws ExecutionException {
Future<Boolean> result = Executors.newSingleThreadExecutor().submit(() -> {
int answer = 43;
assertEquals(42, answer);
return true;
}
assertTrue(result.get());
}
Run Code Online (Sandbox Code Playgroud)
内部断言将抛出一个异常,这会导致result.get()抛出它自己的异常。因此测试将失败,并且异常的原因会告诉您原因(“预期为 42,但实际为 43”)。