JUnit Timeout for Test Method Execution

This tutorial shows how the JUnit Timeout works. You can specify a timeout in JUnit, this means that when a test execution is longer than the specified timeout the test method will fail automatically and be marked as a failure. There are two ways to implement a timeout using JUnit. First is to specify an attribute on the @Test annotation named timeout. The second is to make a global JUnit Rule named Timeout. In the following examples we explain when to use what option.You can optionally specify timeout in milliseconds to cause a test method to fail if it takes longer than that number of milliseconds. If the time limit is exceeded, then the failure is triggered by an Exception being thrown:

JUnit Timeout Attribute on @Test Annotation

You can optionally specify a timeout in milliseconds on the @Test annotation. This will cause the test method to fail when the test execution exceeds the specified timeout by throwing a TestTimedOutException.

Thread safety warning: test methods with a timeout attribute run in a thread other than the thread which runs the fixture’s @Before and @After methods. Make sure your code is thread safe or the test results can vary. Use the Timeout rule instead, which ensures a test method is run on the same thread.
package com.memorynotfound.test;

import org.junit.Test;

public class TimeoutTest {

    @Test(timeout = 1000)
    public void infiniteWhile(){
        while (true);
    }
}

Generated output.

org.junit.runners.model.TestTimedOutException: test timed out after 1000 milliseconds

JUnit Timeout Rules

The timeout specified in the Timeout rule applies to the entire test fixture, including any @Before or @After methods. If the test method runs in an infinite loop for example, then the @After methods will not be called.

The JUnit Timeout Rule applies a global class level timeout. And will throw a TestTimedOutException when a test method execution exceeds the specified timeout.

Global Test Method Timeout with @Rule

When you register the Timeout rule with the @Rule annotation, the rule is applied for all methods in a test class using. This can protect your JUnit tests from long running methods.

package com.memorynotfound.test;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.Timeout;

public class TimeoutRuleTest {

    @Rule
    public Timeout globalTimeout = Timeout.seconds(1);

    @Test
    public void infiniteForLoop(){
        for (;;) {
        }
    }
}

Global Class Timeout with @ClassRule

When you register the Timeout rule with the @ClassRule, then all the methods inside that class must end before the specified timeout. If not, all methods after the specified timeout will fail.

package com.memorynotfound.test;

import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.Timeout;

public class TestTimeoutClassRule {

    @ClassRule
    public static Timeout globalTimeout = Timeout.millis(2500);

    @Test
    public void long_running_method_test1() throws InterruptedException {
        Thread.sleep(2000);
    }

    @Test
    public void long_running_method_test2() throws InterruptedException {
        Thread.sleep(2000);
    }

}

Global Method level timeouts for all classes and methods

You can apply a Timeout either with @Rule or @ClassRule for all the classes/methods inside your test suite.

package com.memorynotfound.test;

import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.rules.Timeout;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({TestA.class, TestB.class})
public class TimeoutSuite {
    
    @ClassRule
    public static Timeout classTimeout = Timeout.seconds(3);
    
    @Rule
    public Timeout timeout = Timeout.millis(1500);
}

References

You may also like...