1. Overview

In this tutorial, we'll look at how we can set timeouts for unit tests using JUnit.

2. Set Timeout for a Single Test

Firstly, let's see setting a timeout for a single test.

For this purpose, we'll use the @Test annotation which has the timeout attribute expecting a value in milliseconds:

@Test(timeout = 1000)
public void shouldTimeout_SinceRuleIsPrioritized() {
    sleep(500);
}

private void sleep(long milliseconds) {
    try {
        Thread.sleep(milliseconds);
    } catch (InterruptedException e) {
        fail();
    }
}

Here, we're setting timeout value as 1000 milliseconds. If the test method doesn't complete in the given time limit, JUnit will throw an exception. More specifically, org.junit.runners.model.TestTimedOutException is thrown.

3. Set Timeout Globally for a Test Class

Now we'll look at setting a timeout for the whole test class.

The Timeout test rule applies given timeout to all tests inside a test class:

@Rule
public Timeout timeout = new Timeout(1000, TimeUnit.MILLISECONDS);

@Test
public void shouldNotTimeout() {
    sleep(500);
}

@Test
public void shouldTimeout() {
    sleep(1500);
}

Here, we're initializing the Timeout test rule with a timeout value of 1000 milliseconds. Similar to the previous example, if operation takes longer than the given timeout value, JUnit will throw an exception.

4. What If Both Timeout Values are Set?

Let's assume that we have a test method whose timeout attribute is set. In addition to that, we also define a Timeout rule in the test class:

@Rule
public Timeout timeout = new Timeout(1000, TimeUnit.MILLISECONDS);

@Test(timeout = 3000)
public void shouldTimeout_SinceRuleIsPrioritized() {
    sleep(1500);
}

When we provide two different timeout values, the smallest one will be effective.

To see why this is the case, we should look at how JUnit implements the timeout mechanism. You can also read the general structure of a JUnit test rule.

But to summarize, JUnit uses FailOnTimeout statement to control timeout behavior. If we set a timeout for a single test, JUnit creates a new instance of FailOnTimeout and wraps the actual test. In addition to that, if we also add the Timeout test rule, JUnit creates another FailOnTimeout statement wrapping the first one. So both will be active, but the smallest one will be the effective one.

5. Summary

In this tutorial, we've explored different ways of setting a timeout on JUnit tests.

Check out the source code for all examples over on Github.