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"因为你现在不知道你的测试到底需要多长时间是 运行。
我在服务的@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"因为你现在不知道你的测试到底需要多长时间是 运行。