In JUnit 5, how to run code before all tests

Solution 1:

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.

Solution 2:

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.

Solution 3:

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.