Junit 测试在我的异步线程上挂起

Junit test hangs up on my async thread

我在服务的@Postconstruct 方法上创建了一个新线程,在新线程中,无限循环是运行。

我的测试只是使用 spring mvc 测试调用服务:

ResultActions result = this.mockMvc.perform(post("/test").with(httpBasic(user, pwd)).contentType("application/json").content(test))
        .andDo(MockMvcResultHandlers.print())
        .andExpect(status().isOk());

测试就挂在那里,等待无限循环线程停止。但是当服务正常启动的时候,测试是没问题的。知道为什么吗?以及如何修复它。

这是我服务中的代码 java:

@Postconstruct
private void init() {
   invoke();
}

private void invoke() {

 Runnable task = () -> {
     while(true) { ... }
  }
 Thread t;
 for(int i=0; i<3; i++) {
     t = new Thread(task);
     t.setName("test-" + i);
     t.start();
  }
 }

看看这个例子(使用调试器)

注意,在所有线程都完成之前,main 不会退出。 您可以通过在 while (运行) 上放置一个断点并缓慢更改 运行 的值来轻松地做到这一点。关闭所有 3 个线程后,您的主线程将退出。

class Test {
    public static void main(String[] args) {
        Runnable task = () -> {
            boolean run = true;
            while (run) {
                System.out.println("running");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        List<Thread> threads = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            Thread t = new Thread(task);
            t.setName("test-" + i);
            t.start();
            threads.add(t);
        }
    }
}

另一种方法是使用 join,它会在程序完成之前明确等待线程完成。

for (Thread t : threads) {
    try {
        t.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

虽然有任何活动线程 运行ning 程序将不会完成。

建议:停止使用 "bare metal" 线程。有很好的抽象概念,比如 ExecutorService 和 Futures 和 Promises 之类的东西。

重点是:可以使用依赖注入为生产代码提供这样的ExecutorService;然后你可以定义你自己的 service ... 在 same 线程上做所有事情。

意思:避免处理多线程的单元测试——因为这通常会导致额外的等待,或者"flakiness"因为你现在不知道你的测试到底需要多长时间是 运行。