Search code examples
javajunitjunit5

How to fail a test after a timeout is exceeded in JUnit 5?


In JUnit 4 the "timeout" annotation parameter can be used to force a test to stop after the given amount of time:

@Test(timeout=100)
public void infinity() {
   while(true);
}

How can this be done in JUnit 5?

Closely related to (and code taken from) timeout parameter for Annotation Type Test, but for JUnit 5.


Solution

  • The strict equivalent of the timeout attribute is the declarative @Timeout annotation.
    From the JUnit 5 documentation :

    The @Timeout annotation allows one to declare that a test, test factory, test template, or lifecycle method should fail if its execution time exceeds a given duration. The time unit for the duration defaults to seconds but is configurable.

    For example :

    @Test
    @Timeout(value = 100, unit = TimeUnit.MILLISECONDS)
    void infinity() { 
      // fails if execution time exceeds 100 milliseconds
      //...
    }
    

    Assertions.assertTimeout() and Assertions.assertTimeoutPreemptively() are new concepts introduced in JUnit 5 (not existing in JUnit 4). These are alternatives to @Timeout that narrow the timeout to a specific set of statements : these defined in the Executable or in the Supplier passed as parameter.
    These two methods (with a very close name) address the same overall goal but with a subtle difference.
    assertTimeoutPreemptively() preemptively aborts the Executable/Supplier if the timeout occurs while assertTimeout() does not.
    To achieve it, assertTimeoutPreemptively() executes the provided Executable/Supplier in a different thread than that of the calling code while assertTimeout() executes it in the same thread.

    Warning from the official documentation : Code/libraries relying on the java.lang.ThreadLocal storage for the test execution setup/teardown may have undesirable side effects with assertTimeoutPreemptively() since that executes the provided statements in a different thread.