My requirement is to have some initialization done for a set of tests and clear it off once all the tests are complete. These tests spin over a few test classes as they are not closely related, but require a common initialization.
I am using @SelectClasses
to form the suite and trying to make use of @ExtendWith
using a custom extension that should handle the pre and post processing. This does not work and I am unsure if an appropriate solution exists in JUnit. Sharing the sample code of what was already attempted.
Suite:
@SelectClasses({FirstTest.class, SecondTest.class})
@ExtendWith(SuiteExtension.class)
@RunWith(JUnitPlatform.class)
@SuiteDisplayName("test suite")
public class SuiteClass {
}
Extension:
public class SuiteExtension implements BeforeAllCallback, AfterAllCallback {
@Override
public void afterAll(ExtensionContext context) throws Exception {
System.out.println("afterAll");
}
@Override
public void beforeAll(ExtensionContext context) throws Exception {
System.out.println("beforeAll");
}
}
Test Class 1:
public class FirstTest {
@Test
void test1(){
System.out.println("test1");
}
}
Test Class 2:
public class SecondTest {
@Test
void test2(){
System.out.println("test2");
}
}
Output:
test1
test2
Expected Output:
beforeAll
test1
test2
afterAll
Combining
@RunWith
(from JUnit 4) and@ExtendWith
(from JUnit Jupiter) is not supported: those are extension mechanisms from two different frameworks.Technically speaking, your
SuiteClass
is a JUnit 4 test class. Thus JUnit Jupiter will not register or execute any extensions for it.With regard to suites in JUnit 5, we (the JUnit Team) have plans to provide first-class support for suites that do not require a JUnit 4 Runner (i.e.,
@RunWith(JUnitPlatform.class)
). See all GitHub issues labeled with "suites" for details. Feel free to watch and/or comment on any of those issues.In the interim, I believe the closest one could come to implementing "before and after suite" support in JUnit Jupiter would be to implement a custom extension that implements
BeforeAllCallback
andAfterAllCallback
. That extension would need to track whether it has already been invoked by storing a flag in the rootExtensionContext
Store
(as aBeforeAllCallback
), so that it only executes once before the "suite". Similarly, it would need to count the number of classes it is executed for and track that in the rootStore
. This would serve as aStack
orCountDownLatch
. As anAfterAllCallback
, the extension would need to decrement the global counter and only execute once all test classes have completed.You'd obviously need to ensure that your suite extension is registered for each test class that belongs to the suite. Perhaps a custom composed annotation would simplify matters for you there.
Now, admittedly, I just implemented that in my head but have not yet actually coded such a "suite" extension. So if you actually implement it, I'd be interested in hearing about your experience and possibly seeing your code. ;-)
Cheers,
Sam (core committer for JUnit 5)