Skip to content

Let @BeforeEach and @AfterEach work around all the tests from a single TestFactory (or introduce a new similar @Before/@After pair) #694

Closed

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 asserts after the whole set of DynamicTests have run.

Also sometimes there is a need to prepare test data for the whole set of DynamicTests.

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 AssertionFailedErrors 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;
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions