JUnit 5 @Timeout

The @Timeout annotation in JUnit 5 allows us to set a maximum time limit for a test or a method. If the test method exceeds the specified time limit, the test will fail automatically. This is useful when we want to ensure that a test does not run …

junit5 logo

The @Timeout annotation in JUnit 5 allows us to set a maximum time limit for a test or a method. If the test method exceeds the specified time limit, the test will fail automatically. This is useful when we want to ensure that a test does not run indefinitely, especially when dealing with long-running or potentially stuck operations.

@Timeout(value = 5) // Test will automatically fail after 5 seconds
@Test
void myTest() {

    // Time consuming operations
}

1. @Timeout Annotation

  • JUnit 5 uses the declarative way to define the timeout behavior of a given test using the @Timeout annotation.
  • 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, another thread interrupts the main 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 is not completed in 3 seconds.

@Test
@Timeout(value = 3, unit = TimeUnit.SECONDS)   // The test will FAIL as it takes more than 3 seconds
void someTest() {
    
    TimeUnit.SECONDS.sleep(5);
}

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

2. Timeout on Test Class

  • 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.
  • 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   // Time out set to 3 seconds
	void testMethodOne() throws InterruptedException {
	    TimeUnit.SECONDS.sleep(5);
	}
	
	@Test
	@Timeout(5)  // Time out set to 5 seconds
	void testMethodTwo() throws InterruptedException {
	    TimeUnit.SECONDS.sleep(4);
	}
}

3. Asserting Timeouts

Sometimes, we may not want to put the timeout limit for the whole test. Rather we want to put a time limit only on a certain block of code. The assertTimeout() and assertTimeoutPreemptively() methods help us achieve the same:

  • assertTimeout: will run the entire code block, even if it exceeds the specified timeout. After the block finishes, it will check how long it took to execute. If it exceeds the timeout, the test will fail after the block completes.
  • assertTimeoutPreemptively: will terminate the block of code as soon as the timeout is exceeded. If the code is still running, it will stop the execution immediately and fail the test right away.

In this example, the assertTimeout method wraps a block of code, and if that block takes longer than the specified timeout, the test will fail.

@Test
void testGetValue_v1() throws InterruptedException {

  Assertions.assertTimeout(Duration.ofSeconds(1), () -> { //FAIL after whole block completes
      getValue();
  });

  System.out.println("This line will be executed even after the timeout failure.");
}

@Test
void testGetValue_v2() throws InterruptedException {

  Assertions.assertTimeoutPreemptively(Duration.ofSeconds(1), () -> {  //FAIL asap timeout occurs
      getValue();
  });

  System.out.println("This line will NOT be executed because of the timeout.");
}

private String getValue() throws InterruptedException {

  TimeUnit.SECONDS.sleep(2);
  return "random-value";
}

4. Configuring Timeout Mode

Disabling timeouts is especially useful when debugging the application code or the test code using breakpoints. When stepping through your code in a debug session, the test may be timed out and marked as 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 supports it, please use this configuration value.

We can configure the timeout mode via junit-platform.properties placed in the src/test/resources directory. This file is automatically picked up by JUnit.

# Setting the timeout mode
junit.jupiter.execution.timeout.mode=enabled

Happy Learning !!

Download Source Code

Weekly Newsletter

Stay Up-to-Date with Our Weekly Updates. Right into Your Inbox.

Comments

Subscribe
Notify of
0 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.