Reputation: 101
I am fork a new thread on my service's @Postconstruct method, and in the new thread, a infinite loop is running.
My test is just invoke the service using spring mvc test:
ResultActions result = this.mockMvc.perform(post("/test").with(httpBasic(user, pwd)).contentType("application/json").content(test))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isOk());
And the test just hangs there, waiting for the infinite loop thread to stop. but when the service is started normally, the test is fine. Any idea why? And how to fix it.
here is the code in my service 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();
}
}
Upvotes: 3
Views: 2441
Reputation: 140457
Suggestion: step back from using "bare metal" Threads. There are nice abstraction concepts, like ExecutorService and things like Futures and Promises.
The point is: one can use dependency injection to provide such an ExecutorService to the production code; and then you can define your own service ... that does everything on the same thread.
Meaning: avoid unit tests that deal with multiple threads - as that often leads to additional waiting, or "flakiness" as you never now exactly how long your test will be running.
Upvotes: 1
Reputation: 2576
Take a look at this example (with a debugger)
Notice that the main will not be exited until all the threads are done. You can easily do this with putting a breakpoint on a while (run) and change the value of run slowly. Once you turn off all 3 threads, then your main thread will exit.
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);
}
}
}
Another way to do it is using join, which will explicitly wait for the threads to finish before the program can complete.
for (Thread t : threads) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
While there are any active threads running the program will not finish.
Upvotes: 0