JUnit 5 @Timeout

Learn to write JUnit 5 tests that can test the timeout behavior of external systems and mocked dependencies.

1. @Timeout Annotation

  • JUnit 5 uses the declarative way to define the timeout behavior of a given test using the @Timeout annotation. It is unlike JUnit 4 @Test timeout attribute.
  • A timeout configured test should fail if its execution time exceeds a given duration. The execution of the test proceeds in the main thread. If the timeout is exceeded, the main thread is interrupted from another thread.
  • The default time unit for the timeout duration is in seconds. We can configure other time units as well.
  • We can apply @Timeout annotation on a :
    • test
    • test factory
    • test template
    • lifecycle method

Given is an example of someTest that should fail if the execution does not complete in 3 seconds.

@BeforeEach
@Timeout(2)
void setUp() {
    // fails if execution time exceeds 2 seconds
}

@Test
@Timeout(3)
void someTest() {
    TimeUnit.SECONDS.sleep(5);
}

The above test will fail with reason: java.util.concurrent.TimeoutException: someTest() timed out after 3 seconds.

2. Global Timeouts

  • To configure the timeout for all the tests and nested tests, we can apply the @Timeout annotation at the class level.
  • @Timeout annotations declared at the class level are not applied to lifecycle methods.
  • We can override the timeout on a certain test by applying the @Timeout annotation on that test.
  • When applied with @RepeatedTest or @ParameterizedTest, the timeout is applied on each invocation of the test.

In the given example, testMethodOne will FAIL and testMethodTwo will PASS.

@Timeout(3)
public class TimeoutTests {

	@Test
	void testMethodOne() throws InterruptedException {
	    TimeUnit.SECONDS.sleep(5);
	}
	
	@Test
	@Timeout(5)
	void testMethodTwo() throws InterruptedException {
	    TimeUnit.SECONDS.sleep(4);
	}
}

3. Assertions.assertTimeout()

The assertTimeout() method asserts that execution of the supplied code completes before the given timeout is exceeded.

The given test will PASS because the method execution is completed in 2 seconds while assertTimeout() waits for 3 seconds.

@Test
void testGetValue() throws InterruptedException {
    Assertions.assertTimeout(Duration.ofSeconds(3), () -> {
        getValue();
    });
}

String getValue() throws InterruptedException {
	TimeUnit.SECONDS.sleep(2);
	return "";
}

4. Disable @Timeout Globally

Disabling timeouts is specially useful when debugging the application code or the test code using breakpoints. In this case, the test may be timed out and marked failed even though all other assertions were true.

Use junit.jupiter.execution.timeout.mode configuration parameter to configure the timeout behavior. Its values are:

  • enabled (default mode) – Enables the timeout globally.
  • disabled – Disables the timeout globally.
  • disabled_on_debug – The IDEs may be supporting this property already. In case, your IDE does not support it, please use this configuration value.

Happy Learning !!

Download Source Code

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.