JUnit Jupiter, aka "JUnit 5": use @BeforeAll
If you use the newer JUnit Jupiter (Java 8 onward), you'll want to replace @Before
with @BeforeAll
.
Furthermore, you'll need to either annotate your test class with @TestInstance(Lifecycle.PER_CLASS)
or make the @BeforeAll
method static
. Here's an example:
@TestInstance(Lifecycle.PER_CLASS)
class MyTestClass {
MyHeavyResource sharedResource;
@BeforeAll
void init() {
System.out.println("init");
sharedResource = new MyHeavyResource(1234);
}
@Test
void myTest() {
System.out.println("myTest");
sharedResource.methodUnderTest();
}
}
Understanding Lifecycle.PER_CLASS
The likely reason JUnit 5 is more stringent with this -- demanding either static
or Lifecycle.PER_CLASS
-- is that it wants the test author to acknowledge that any resource instance initialized in a @BeforeAll
method will genuinely be shared across each individual unit test method within the class. This could compromise their isolation, for example if the sharedResource
in the above example isn't stateless/idempotent.
If sharedResource
cannot be safely shared (or if it's reasonably leightweight), the init
method should be annotated with @BeforeEach
instead, which would create a new instance before executing each individual test within the class.
The Javadoc for TestInstance
explain how using Lifecycle.PER_CLASS
actually enforces a single instance of the test class; whereas the behaviour of JUnit 4 and earlier was equivalent to Lifecycle.PER_METHOD
, which created a new instance of the test class for each @Test
method contained therein. This would somewhat mislead the author to suppose that @Before
was only executed once for each of those tests.