5.9. Test Lifecycle Callbacks

The following interfaces define the APIs for extending tests at various points in the test execution lifecycle. Consult the following sections for examples and the Javadoc for each of these interfaces in the [org.junit.jupiter.api.extension](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/extension/package-summary.html) package for further details.

  • [BeforeAllCallback](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/extension/BeforeAllCallback.html)

    • [BeforeEachCallback](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/extension/BeforeEachCallback.html)

      • [BeforeTestExecutionCallback](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/extension/BeforeTestExecutionCallback.html)

      • [AfterTestExecutionCallback](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/extension/AfterTestExecutionCallback.html)

    • [AfterEachCallback](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/extension/AfterEachCallback.html)

  • [AfterAllCallback](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/extension/AfterAllCallback.html)

Implementing Multiple Extension APIs
Extension developers may choose to implement any number of these interfaces within a single extension. Consult the source code of the SpringExtension for a concrete example.

5.9.1. Before and After Test Execution Callbacks

[BeforeTestExecutionCallback](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/extension/BeforeTestExecutionCallback.html) and [AfterTestExecutionCallback](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/extension/AfterTestExecutionCallback.html) define the APIs for Extensions that wish to add behavior that will be executed immediately before and immediately after a test method is executed, respectively. As such, these callbacks are well suited for timing, tracing, and similar use cases. If you need to implement callbacks that are invoked around @BeforeEach and @AfterEach methods, implement BeforeEachCallback and AfterEachCallback instead.

The following example shows how to use these callbacks to calculate and log the execution time of a test method. TimingExtension implements both BeforeTestExecutionCallback and AfterTestExecutionCallback in order to time and log the test execution.

An extension that times and logs the execution of test methods

  1. import java.lang.reflect.Method;
  2. import java.util.logging.Logger;
  3. import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
  4. import org.junit.jupiter.api.extension.BeforeTestExecutionCallback;
  5. import org.junit.jupiter.api.extension.ExtensionContext;
  6. import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
  7. import org.junit.jupiter.api.extension.ExtensionContext.Store;
  8. public class TimingExtension implements BeforeTestExecutionCallback, AfterTestExecutionCallback {
  9. private static final Logger logger = Logger.getLogger(TimingExtension.class.getName());
  10. private static final String START_TIME = "start time";
  11. @Override
  12. public void beforeTestExecution(ExtensionContext context) throws Exception {
  13. getStore(context).put(START_TIME, System.currentTimeMillis());
  14. }
  15. @Override
  16. public void afterTestExecution(ExtensionContext context) throws Exception {
  17. Method testMethod = context.getRequiredTestMethod();
  18. long startTime = getStore(context).remove(START_TIME, long.class);
  19. long duration = System.currentTimeMillis() - startTime;
  20. logger.info(() ->
  21. String.format("Method [%s] took %s ms.", testMethod.getName(), duration));
  22. }
  23. private Store getStore(ExtensionContext context) {
  24. return context.getStore(Namespace.create(getClass(), context.getRequiredTestMethod()));
  25. }
  26. }

Since the TimingExtensionTests class registers the TimingExtension via @ExtendWith, its tests will have this timing applied when they execute.

A test class that uses the example TimingExtension

  1. @ExtendWith(TimingExtension.class)
  2. class TimingExtensionTests {
  3. @Test
  4. void sleep20ms() throws Exception {
  5. Thread.sleep(20);
  6. }
  7. @Test
  8. void sleep50ms() throws Exception {
  9. Thread.sleep(50);
  10. }
  11. }

The following is an example of the logging produced when TimingExtensionTests is run.

  1. INFO: Method [sleep20ms] took 24 ms.
  2. INFO: Method [sleep50ms] took 53 ms.