[英]How to get ExecutorService or CompletionService to finish without asking for values of Futures?
我们需要在一个线程中完成一些工作,该线程将使用Spring Boot在Web应用程序的服务器上运行。
我们想要发生的是:1)工作作为我们的自定义Runnable对象提交2)工作轮到它完成时(它是数据库操作,并且不需要任何返回值,除非运行即可返回“成功” ()已完成,无例外)
但是,在我们的JUnit测试中,似乎主线程完成后,提交给ExecutorService或CompletionService的所有任务都会消失,除非每次添加新任务时都调用take()(因为它阻塞直到任务完成,所以这使任务按顺序运行(这会违背目的)),或者如果我们维护期货列表并调用一种方法来遍历列表并获取每个功能的值的方法。
我们认为后一种选择不是理想的选择,因为作为服务器应用程序,我们将不断收到来自不同用户的请求,并且不知道如何检测何时应该清除期货清单。
为什么线程会静默消失,如何解决呢?
不要异步运行代码:只需直接测试Runnable
:
@Test
public void test() {
Runnable r = <your runnable>;
r.run();
// various assertions
}
您选择的ExecutorService
完成其工作是毫无意义的测试-您可以假设这样做。
如果您想断言您的应用程序行为正确,请使用功能测试; 即,使用超音速数据源启动一个容器(例如,使用@SpringJUnit4ClassRunner
),击中spring boot的端点,然后使您断言对数据库的影响。
如果您对服务使用spring boot的@Async
批注,则甚至可以提供使用SynchronousTaskExecutor
的配置,因此您不必在断言之前暂停测试。
测试异步代码的一种好方法是使用ConcurrentUnit之类的方法阻塞主测试线程并在回调中执行断言。 这是一个使用CompletableFuture的whenComplete
回调的whenComplete
:
Waiter waiter = new Waiter();
CompletableFuture<Connection> future = someService.connect();
future.whenComplete((connection, failure) -> {
// Called from some other thread
waiter.assertNotNull(connection);
waiter.assertNull(failure);
waiter.resume();
});
// Block the main test thread
waiter.await();
如果回调线程中的任何一个声明失败,则测试将按预期失败。 主测试线程将在完成测试之前等待resume
调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.