Shuai Junlan
Shuai Junlan

Reputation: 595

Differences between tesing multi-thread in JUnit and Main function in Java

I tested a multi-thread program in JUnit and main function, source code as follows:

public class TestDaemon {
    @Test
    public void test() {
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(1000);
                System.out.println("hello");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        // default false
        thread.setDaemon(false);
        thread.start();
    }
    public static void main(String[] args) {

        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(1000);
                System.out.println("hello");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        // default false
        thread.setDaemon(false);
        thread.start();

    }
}

It didn't print hello string in the JUnit test example.
In the main function example, it could print hello in the console, but when I set the thread.setDaemon(true), it also can't print hello.

I know this is related to Daemon thred and User thread, but I don't know how to explain it.

Upvotes: 0

Views: 154

Answers (2)

Shuai Junlan
Shuai Junlan

Reputation: 595

We can analyze the source code of JUnit, part of junit.textui.TestRunner as follows:

public static final int SUCCESS_EXIT = 0;
public static final int FAILURE_EXIT = 1;
public static final int EXCEPTION_EXIT = 2;

...

public static void main(String args[]) {
    TestRunner aTestRunner = new TestRunner();
    try {
        TestResult r = aTestRunner.start(args);
        if (!r.wasSuccessful()) {
            System.exit(FAILURE_EXIT);
        }
        System.exit(SUCCESS_EXIT);
    } catch (Exception e) {
        System.err.println(e.getMessage());
        System.exit(EXCEPTION_EXIT);
    }
}
/**
 * Returns whether the entire test was successful or not.
 */
public synchronized boolean wasSuccessful() {
    return failureCount() == 0 && errorCount() == 0;
}
/**
 * Gets the number of detected failures.
 */
public synchronized int failureCount() {
    return fFailures.size();
}
/**
 * Gets the number of detected errors.
 */
public synchronized int errorCount() {
    return fErrors.size();
}

In this source code, we can conclude that the TestRunner excutes the Unit Test method, no need to wait it finish their tasks, then calls System.exit() method, so that terminates the program. So, it couldn't print hello in the console.

In the main function, because the new thread is not daemon thread, the main program will wait it finishing their tasks, then teminates the program. So,hellostring could be seen in the console.

Upvotes: 0

Ediz Uslu
Ediz Uslu

Reputation: 119

A daemon thread is a thread that does not prevent the JVM from exiting when the program finishes but the thread is still running. An example for a daemon thread is the garbage collection.

When you run your code from main it creates both beans, thus two threads - daemon and non-daemon. As long as non-daemon thread is running, your application won't exit. So it works.

It's different when run from JUnit. As soon as JUnit test method completes (and it completes immediately after the Spring context is up), JUnit assumes your tests are done. Thus it kills all your threads and basically the whole JVM.

Remember your Waitor1 bean spawns a background thread which JUnit doesn't care about. As soon as you leave @Test method JUnit will just stop everything.

Upvotes: 3

Related Questions