The @BeforeAll
annotation marks a method to run before all tests in a class.
http://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations
But is there a way to run some code before all tests, in all classes?
I want to ensure that tests use a certain set of database connections, and the global one-time setup of these connections must occur before running any tests.
Currently this is not supported, but there is a pull request for JUnit 5 regarding this topic: Introduce support for before/after callbacks once per entire test run.
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.
You can mark each of your test classes that uses your database with an interface that defines a static
BeforeAll
(so that it cannot be overridden). e.g.:
interface UsesDatabase {
@BeforeAll
static void initializeDatabaseConnections() {
// initialize database connections
}
}
This method will be invoked once for each implementing class so you will need to define a way to initialize your connections only once and then do nothing for the other calls.
I am not aware of a mean to do that.
I would simply make sure that all code for @BeforeAll calls a certain singleton to make that init work (probably in a lazy way to avoid repetition).
Probably not convenient ... the only other option I see: I assume your tests run within a specific JVM job. You could hook an agent into that JVM run, that does that init work for you.
Beyond that: both suggestions sounds somehow like a hack to me. The real answer in my eyes: step back, and carefully examine your environment on its dependencies. And then find a way to prepare your environment in a way that your tests come up and the "right thing" happens automatically. In other words: consider looking into the architecture that bought you this problem.
Above advises do not work for me, so I solved this problem like this:
Add to your Base abstract class (I mean abstract class where you initialize your driver in setUpDriver() method) this part of code:
private static boolean started = false;
static{
if (!started) {
started = true;
try {
setUpDriver(); //method where you initialize your driver
} catch (MalformedURLException e) {
}
}
}
And now, if your test classes will extends from Base abstract class -> setUpDriver() method will be executed before first @Test only ONE time per project run.