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 theTimeout 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);
}