【问题标题】:Test spring application that comes with a blocking ApplicationRunner测试带有阻塞 ApplicationRunner 的 spring 应用程序
【发布时间】:2019-09-06 14:46:40
【问题描述】:

我正在编写一个 Spring 应用程序的测试。这个应用程序带有一个ApplicationRunner(我们称之为AppRunner),它通过自动配置捆绑在一起。并且一旦被调用(即 Spring 自动调用 AppRunner.run()),这个 AppRunner 将轮询一些 kafka 主题,阻塞直到它收到一条消息,处理它,然后如果没有人调用 stop(),则循环。

现在,我想在测试中做的是启动应用程序并“并行”执行推送 kafka 消息的测试并检查输出是否有效。

但是AppRunner.run 在@Test 之前被调用,一切都卡住了。

=> 我应该如何运行我的测试?是否可以配置 spring (boot) 测试以异步运行AppRunner

这不是一个 Web 应用程序,但我希望 Spring Web 应用程序(测试)能够异步运行。也许有使用类似系统的解决方案(?)。

【问题讨论】:

  • 您是否尝试在测试类中定义 ApplicationRunner 类型的模拟 bean,并执行 Mockito.doNothing().when(appRunner).run(any());
  • 我实际上需要 AppRunner,它是测试的一部分。

标签: spring spring-boot unit-testing asynchronous


【解决方案1】:

我必须重写 AppRunner 并重写 run 方法以异步运行。像这样的:

public class AsyncAppRunner extends AppRunner {

    private ExecutorService executorService = Executors.newFixedThreadPool(1);
    private Option<Future<?>> runningTask = Option.empty();

    public AsyncAppRunner(Dep1 dep1, Dep2, dep2 /*...*/) {
        super(dep1, dep2);
    }

    @Override
    public void run(ApplicationArguments args) {
        if(runningTask.isDefined()) throw new RuntimeException("already running");
        runningTask = Option.apply(executorService.submit(() -> super.run(args)));
    }

    void stopAndWait() throws InterruptedException, ExecutionException, TimeoutException {
        if(runningTask.isDefined()){
            super.stop(); // method of the AppRunner that stop the infinite loop
            runningTask.get().get(1L, TimeUnit.MINUTES);
            runningTask = Option.empty();
        } else {
            throw new RuntimeException("No task running");
        }
    }
}

并将这个类添加到 SpringBootTest 类中:

@SpringBootTest(classes = {..., AsynAppRunner.class })
public class MyAppTest {
    ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-17
    • 1970-01-01
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多