The assertTimeoutPreemptively method in JUnit is used to assert that a block of code completes execution before a specified timeout is exceeded, and it does so by preemptively terminating the execution if the timeout is exceeded. JUnit provides several overloaded versions of this method to handle different scenarios and to provide custom messages for test failures. This guide covers the basics of using the assertTimeoutPreemptively method, including its syntax and examples of its different overloads.
Table of Contents
- Introduction
assertTimeoutPreemptivelyMethod Syntax- Examples
- Basic Usage
- Using a Custom Message
- Using a Message Supplier
- Returning a Value
- Real-World Use Case
- Conclusion
Introduction
The assertTimeoutPreemptively method in JUnit is an assertion method used to verify that a given block of code completes execution within a specified timeout by preemptively terminating the execution if it exceeds the timeout. This is different from assertTimeout, which waits for the execution to complete even if the timeout is exceeded. This method is useful for ensuring that tests do not hang indefinitely.
assertTimeoutPreemptively Method Syntax
Here is the basic syntax of the assertTimeoutPreemptively method with its different overloads:
// Asserts that the supplied executable completes before the given timeout is exceeded
static void assertTimeoutPreemptively(Duration timeout, Executable executable);
// Asserts that the supplied executable completes before the given timeout is exceeded with a custom message
static void assertTimeoutPreemptively(Duration timeout, Executable executable, String message);
// Asserts that the supplied executable completes before the given timeout is exceeded with a custom message supplier
static void assertTimeoutPreemptively(Duration timeout, Executable executable, Supplier<String> messageSupplier);
// Asserts that the supplied supplier completes before the given timeout is exceeded and returns the value
static <T> T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier<T> supplier);
// Asserts that the supplied supplier completes before the given timeout is exceeded with a custom message and returns the value
static <T> T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier<T> supplier, String message);
// Asserts that the supplied supplier completes before the given timeout is exceeded with a custom message supplier and returns the value
static <T> T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier<T> supplier, Supplier<String> messageSupplier);
// Asserts that the supplied supplier completes before the given timeout is exceeded with a custom failure factory
static <T,E extends Throwable> T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier<T> supplier, Supplier<String> messageSupplier, Assertions.TimeoutFailureFactory<E> failureFactory);
Parameters:
timeout: The maximum duration that the executable or supplier is allowed to run.executable: The block of code to be executed.supplier: A supplier that provides the value to be returned and checked for the timeout.message: Optional. A custom message to display if the assertion fails.messageSupplier: Optional. A supplier that provides a custom message to display if the assertion fails.failureFactory: Optional. A factory that creates a custom exception when the timeout is exceeded.
Returns:
- The value returned by the supplier, if no exception is thrown and the timeout is not exceeded.
Examples
Basic Usage
Verify that a block of code completes execution within the specified timeout preemptively.
Example
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
import org.junit.jupiter.api.Test;
import java.time.Duration;
public class TimeoutPreemptivelyTest {
@Test
void testTimeoutPreemptively() {
assertTimeoutPreemptively(Duration.ofSeconds(1), () -> {
// Simulate a task that completes within 1 second
Thread.sleep(500);
});
}
}
Using a Custom Message
Include a custom message to display if the assertion fails.
Example
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
import org.junit.jupiter.api.Test;
import java.time.Duration;
public class CustomMessageTest {
@Test
void testTimeoutPreemptivelyWithMessage() {
assertTimeoutPreemptively(Duration.ofSeconds(1), () -> {
// Simulate a task that completes within 1 second
Thread.sleep(500);
}, "The task should complete within 1 second");
}
}
Using a Message Supplier
Use a message supplier to lazily generate a custom message if the assertion fails.
Example
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
import org.junit.jupiter.api.Test;
import java.time.Duration;
import java.util.function.Supplier;
public class MessageSupplierTest {
@Test
void testTimeoutPreemptivelyWithMessageSupplier() {
Supplier<String> messageSupplier = () -> "The task should complete within 1 second";
assertTimeoutPreemptively(Duration.ofSeconds(1), () -> {
// Simulate a task that completes within 1 second
Thread.sleep(500);
}, messageSupplier);
}
}
Returning a Value
Verify that a block of code completes execution within the specified timeout preemptively and return the value.
Example
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import java.time.Duration;
public class ReturnValueTest {
@Test
void testTimeoutPreemptivelyWithReturnValue() {
int result = assertTimeoutPreemptively(Duration.ofSeconds(1), () -> {
// Simulate a task that completes within 1 second and returns a value
Thread.sleep(500);
return 42;
});
assertEquals(42, result);
}
}
Using a Custom Message with Return Value
Include a custom message to display if the assertion fails and return the value.
Example
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import java.time.Duration;
public class ReturnValueWithMessageTest {
@Test
void testTimeoutPreemptivelyWithReturnValueAndMessage() {
int result = assertTimeoutPreemptively(Duration.ofSeconds(1), () -> {
// Simulate a task that completes within 1 second and returns a value
Thread.sleep(500);
return 42;
}, "The task should complete within 1 second and return the correct value");
assertEquals(42, result);
}
}
Real-World Use Case
Testing a FileService Class
A common use case for assertTimeoutPreemptively is testing methods that perform time-sensitive operations in a FileService class. For example, verifying that a method reads a file within a specified timeout.
Class Under Test – FileService
import java.time.Duration;
import java.util.List;
import java.util.Arrays;
public class FileService {
public List<String> readFile() throws InterruptedException {
// Simulate a file reading operation
Thread.sleep(500);
return Arrays.asList("Line 1", "Line 2", "Line 3");
}
}
Test Class – FileServiceTest
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
public class FileServiceTest {
private final FileService fileService = new FileService();
@Test
void testReadFileTimeoutPreemptively() {
List<String> lines = assertTimeoutPreemptively(Duration.ofSeconds(1), () -> {
return fileService.readFile();
}, "The file reading operation should complete within 1 second");
assertEquals(Arrays.asList("Line 1", "Line 2", "Line 3"), lines);
}
}
In this example, the FileServiceTest class tests the readFile method of the FileService class using assertTimeoutPreemptively. It includes tests to ensure that the method completes the file reading operation within the specified timeout.
Conclusion
The assertTimeoutPreemptively method in JUnit is used for verifying that a given block of code completes execution within a specified timeout by preemptively terminating the execution if it exceeds the timeout. By using assertTimeoutPreemptively and its various overloads, you can ensure that your tests provide clear feedback when operations take longer than expected. Understanding and using the assertTimeoutPreemptively method effectively is crucial for developing robust and maintainable Java applications.