In JUnit 5, how to run code before all tests In JUnit 5, how to run code before all tests java java

In JUnit 5, how to run code before all tests


This is now possible in JUnit5 by creating a custom Extension, from which you can register a shutdown hook on the root test-context.

Your extension would look like this;

import org.junit.jupiter.api.extension.BeforeAllCallback;import org.junit.jupiter.api.extension.ExtensionContext;import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL;public class YourExtension implements BeforeAllCallback, ExtensionContext.Store.CloseableResource {    private static boolean started = false;    @Override    public void beforeAll(ExtensionContext context) {        if (!started) {            started = true;            // Your "before all tests" startup logic goes here            // The following line registers a callback hook when the root test context is shut down            context.getRoot().getStore(GLOBAL).put("any unique name", this);        }    }    @Override    public void close() {        // Your "after all tests" logic goes here    }}

Then, any tests classes where you need this executed at least once, can be annotated with:

@ExtendWith({YourExtension.class})

When you use this extension on multiple classes, the startup and shutdown logic will only be invoked once.


The already provided answer from @Philipp Gayret has some problems when testing JUnit in parallel (i.e. junit.jupiter.execution.parallel.enabled = true).

Therefore I adapted the solution to:

import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;import org.junit.jupiter.api.extension.BeforeAllCallback;import org.junit.jupiter.api.extension.ExtensionContext;public class BeforeAllTestsExtension extends BasicTestClass        implements BeforeAllCallback, ExtensionContext.Store.CloseableResource {    private static boolean started = false;    // Gate keeper to prevent multiple Threads within the same routine    final static Lock lock = new ReentrantLock();    @Override    public void beforeAll(final ExtensionContext context) throws Exception {        // lock the access so only one Thread has access to it        lock.lock();        if (!started) {            started = true;            // Your "before all tests" startup logic goes here            // The following line registers a callback hook when the root test context is            // shut down            context.getRoot().getStore(GLOBAL).put("any unique name", this);            // do your work - which might take some time -             // or just uses more time than the simple check of a boolean        }        // free the access        lock.unlock();    }    @Override    public void close() {        // Your "after all tests" logic goes here    }}

As mentioned below JUnit5 provides an automatic Extension Registration. To do so add a in src/test/resources/ a directory called /META-INF/services and add a file named org.junit.jupiter.api.extension.Extension. Add into this file the fully classified name of your class, e.g.

at.myPackage.BeforeAllTestsExtension

Next enable in the same Junit config file

junit.jupiter.extensions.autodetection.enabled=true

With this the extension is attached automatically to all of your tests.


Extending on suggestion from @Philipp, here's a more complete code snippet:

import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL;    import org.junit.jupiter.api.extension.BeforeAllCallback;import org.junit.jupiter.api.extension.ExtensionContext;public abstract class BaseSetupExtension    implements BeforeAllCallback, ExtensionContext.Store.CloseableResource {  @Override  public void beforeAll(ExtensionContext context) throws Exception {    // We need to use a unique key here, across all usages of this particular extension.    String uniqueKey = this.getClass().getName();    Object value = context.getRoot().getStore(GLOBAL).get(uniqueKey);    if (value == null) {      // First test container invocation.      context.getRoot().getStore(GLOBAL).put(uniqueKey, this);      setup();    }  }  // Callback that is invoked <em>exactly once</em>   // before the start of <em>all</em> test containers.  abstract void setup();  // Callback that is invoked <em>exactly once</em>   // after the end of <em>all</em> test containers.  // Inherited from {@code CloseableResource}  public abstract void close() throws Throwable;}

How to use:

public class DemoSetupExtension extends BaseSetupExtension {  @Override  void setup() {}  @Override  public void close() throws Throwable {}}  @ExtendWith(DemoSetupExtension.class)public class TestOne {   @BeforeAll   public void beforeAllTestOne { ... }   @Test   public void testOne { ... }}@ExtendWith(DemoSetupExtension.class)public class TestTwo {   @BeforeAll   public void beforeAllTestTwo { ... }   @Test   public void testTwo { ... }}

Test execution order will be:

  DemoSetupExtension.setup (*)  TestOne.beforeAllTestOne  TestOne.testOne  TestOne.afterAllTestOne  TestTwo.beforeAllTestTwo  TestTwo.testTwo  TestTwo.afterAllTestTwo  DemoSetupExtension.close (*)

...this will be true regardless if you choose to run a single @Test (e.g.TestOne.testOne), or an entire test class (TestOne), or multiple / all tests.