简体   繁体   中英

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.

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.

Use the assertTimeoutPreemptively static assertion from org.junit.jupiter.api.Assertions :

@Test
public void infinity() {
    assertTimeoutPreemptively(Duration.ofMillis(100), () -> {
        while (true);
    });
}

In addition to the other answers which specify a timeout for a specific test (per the OP request), beginning in JUnit 5.5 it is also possible to configure a global timeout, a useful option instead of adding the @Timeout annotation to every method.

Per the JUnit 5 User Guide , which documents the syntax in the other answers:

configuration parameters can be used to specify global timeouts for all methods of a certain category unless they or an enclosing test class is annotated with @Timeout

For example, this would set a global timeout of 500 milliseconds for all testable and lifecycle methods:

junit.jupiter.execution.timeout.default = 500 ms

The timeouts can be more narrowly scoped, for example just @Test methods:

junit.jupiter.execution.timeout.testtemplate.method.default = 500 ms

The @Timeout annotation described in the other answers will override these defaults if it is used.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM