JUnit 5 timeout example
In some cases you are required to check if a method execution is completed within expected time say 500 ms. It not then the JUnit test should fail. For e.g. setup of JUnit test or connecting to DB or method execution, etc. To achieve this you can use @Timeout
annotation with specified time limit in seconds, ms, ns, etc. and also using assertTimeout
This example shows JUnit 5 timeout examples.
1) Add below dependencies to pom.xml
<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.8.1</version> <scope>test</scope></dependency>
2) Write a Calculator class with time consuming factorial method.
public class Calculator { public long factorial(int number) { if (number == 1) { return 1; } return number * factorial(number - 1); } }
3) Write CalculatorTest class using JUnit 5 which tests factorial() method of Calculator Class by @Timeout
annotation.
@Timeout
annotation by default uses seconds as unit of time. You can change the unit by specifying value and unit attributes. In below tests, test setup will fail if takes more than 2 sec. testFactorialWithTimeout test will fail if factorial takes more than 5 sec. testFactorialWithLessTimeout test will fail if it takes more than 1 nanoseconds.
import org.junit.jupiter.api.BeforeEach;import org.junit.jupiter.api.Test;import org.junit.jupiter.api.Timeout; public class CalculatorTest { @BeforeEach @Timeout(2) void setUp() { System.out.println("Sleeping for 1 sec"); try { Thread.sleep(1000); } catch (InterruptedException e) { // throws exception if time taken is more than 1 sec e.printStackTrace(); } } @Test @Timeout(5) public void testFactorialWithTimeout() { Calculator calculator = new Calculator(); System.out.println("Calling factorial"); System.out.println(calculator.factorial(30)); } // fails if time taken is more than 1 ns @Test @Timeout(value = 1, unit = TimeUnit.NANOSECONDS) public void testFactorialWithLessTimeout() { Calculator calculator = new Calculator(); System.out.println("Calling factorial"); System.out.println(calculator.factorial(1000)); } }
testFactorialWithLessTimeout test fails with below error message as it takes more than 1 nanosecond
java.util.concurrent.TimeoutException: testFactorialWithLessTimeout() timed out after 1 nanosecond at org.junit.jupiter.engine.extension.TimeoutInvocation. createTimeoutException (TimeoutInvocation.java:70) at org.junit.jupiter.engine.extension.TimeoutInvocation.proceed (TimeoutInvocation.java:59)
4) Test CalculatorTest using assertTimeout
You can also test timeout using assertTimeout
as shown below. In this case you do not need to use @Timeout
.
import static java.time.Duration.ofMillis;import static java.time.Duration.ofNanos;import static org.junit.jupiter.api.Assertions.assertEquals;import static org.junit.jupiter.api.Assertions.assertTimeout;import java.util.concurrent.TimeUnit;import org.junit.jupiter.api.Test; public class CalculatorTest { @Test public void testFactorialTimeout() { Calculator calculator = new Calculator(); System.out.println("Calling factorial"); // throws exception if time taken is more than 1 ns long actualResult = assertTimeout(ofNanos(1), () -> { return calculator.factorial(10); }); assertEquals(3628800, actualResult); } @Test public void testTimeout() { assertTimeout(ofMillis(10), () -> { Thread.sleep(100); }); }}
References :
Timeout JUnit 5.5.1
JUnit 5 User Guide