mainas
mainas

Reputation: 754

Strange behavior when testing multi-threading in junit

I bumped into a problem which caused me to really get stumped for a while. I'm sure it's something about junit I'm not quite savvy with.

Let's tak a very simple class:

package incubate.thread;

import java.util.logging.Level;
import java.util.logging.Logger;

public class Sleeper implements Runnable{

    @Override
    public void run(){
        try {
            Thread.sleep(5000l);
            System.out.println("done snoozing");
        } catch (InterruptedException ex) {
            Logger.getLogger(Sleeper.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

Write a very simple test for the thread

package incubate.thread;

import org.junit.Test;

public class SleeperTest {

    @Test
    public void testSnooze() throws Exception {
        new Thread(new Sleeper()).start();
    }

    public static void main(String...args){
        new Thread(new Sleeper()).start();
    }
}

You will notice I have included a "main" method inside the test class. When you invoke junit to execute "testSnooze", the test immediately exits without running the thread.

If however you invoke the main method, the thread runs just fine; it snoozes and then prints the quick message at the end

What about junit causes this behavior?

Upvotes: 0

Views: 209

Answers (2)

Jaroslaw Pawlak
Jaroslaw Pawlak

Reputation: 5578

Further on ThomasStets' answer, I would suggest to consider testing run() method on its own, without calling Thread's start().

The purpose of testing is to test the code we wrote, we should not test the code we didn't write - so for the unit test, calling the run() method directly should be sufficient.

However, we should test that the code we wrote works with the code we didn't write. In case as simple as threads, I think this would be covered in acceptance test (black-box test on the entry point to the system), there is no really way to write integration test for this.

Upvotes: 2

Thomas Stets
Thomas Stets

Reputation: 3035

Your testSnooze will return without waiting for the thread to finish. Not sure what will happen to the still sleeping thread when JUnit finishes. I guess JUnit just exits the VM without waiting for any residual threads.

If you invoke the main method, the VM will wait for any non-deamon threads to finish.

For your test to work just wait for the Thread to finish:

@Test
public void testSnooze() throws Exception {
    Thread t = new Thread(new Sleeper());
    t.start();
    t.join();
}

Upvotes: 1

Related Questions