Description
Overview
JUnit is used not only for pure unit tests (where each unit test should be completely independent), but often also for (some kind of) integration tests. Sometimes it is extremely useful if you may assert some conditions after a bunch of tests have run. The new @TestFactory
feature would be an excellent place for it if there were a place for adding assert
s after the whole set of DynamicTest
s have run.
Also sometimes there is a need to prepare test data for the whole set of DynamicTest
s.
The documentation says
The execution lifecycle of a dynamic test is quite different than it is for a standard
@Test
case. Specifically, there are not any lifecycle callbacks for dynamic tests. This means that@BeforeEach
and@AfterEach
methods and their corresponding extension callbacks are not executed for dynamic tests. In other words, if you access fields from the test instance within a lambda expression for a dynamic test, those fields will not be reset by callback methods or extensions between the execution of dynamic tests generated by the same@TestFactory
method.
However, it may be nice either having @BeforeEach
and @AfterEach
working before and after the whole bunch of dynamic tests called by one @TestFactory
test, or introducing a new pair of @BeforeXXX
and @AfterXXX
annotation for the same purpose.
Currently, @BeforeEach
and @AfterEach
does not run at all. @BeforeAll
and @AfterAll
runs, but they are run only once and AssertionFailedError
s in @AfterAll
are swallowed and not reported.
Code example
The following is currently not possible. Some useful use cases can be easily created if the mechanism worked.
public class AssertAfterDynamicTestsTest {
private int countOfVowels;
@BeforeEach
public void init() {
// Currently does not run at all
countOfVowels = 0;
// and prepare some data for the set of DynamicTests
}
@AfterEach
public void cleanUp() {
// Currently does not run at all
assertEquals(3, countOfVowels, "The test should have encountered 3 vowels");
}
@TestFactory
public Stream<DynamicTest> doSomeTestsWhichSetI() {
return Stream.of("A", "B", "C", "D", "E", "F", "G", "H", "I", "J")
.map(s -> DynamicTest.dynamicTest(
"Testing for " + s,
() -> {
final char firstChar = s.charAt(0);
assertTrue(Character.isUpperCase(firstChar));
if (isVowel(firstChar)) {
countOfVowels++;
}
}
));
}
private boolean isVowel(char c) {
return "AEIOUaeiou".indexOf(c) != -1;
}
}