Search code examples
javaunit-testingintegration-testingjunit5junit-jupiter

Junit ParameterizedTest with expensive setup


Im looking for a way of optimize running multiple parameterized tests with expensive setup

my current code looks like this

    @ParameterizedTest
    @MethodSource("test1CasesProvider")
    void test1(String param) {
        // expensive setup code 1
        
        // execution & assertions
    }

    @ParameterizedTest
    @MethodSource("test2CasesProvider")
    void test2(String param) {
        // expensive setup code 2
        
        // execution & assertions
    }

but in that shape expensive setup runs for every testCase, which is not very good I can split this test into two separate tests and use @BeforeAll, then setup runs only once per test, but im looking for a way to keep both cases in one test


Solution

  • You can use @Nested tests in this case, like this way:

    public class MyTests {
    
        @Nested
        @TestInstance(TestInstance.Lifecycle.PER_CLASS)
        class Test1Cases {
    
            @BeforeAll
            void setUpForTest1() {
                System.out.println("Test1Cases: setting up things!");
            }
    
            @AfterAll
            void tearDownForTest1() {
                System.out.println("Test1Cases: tear down things!");
            }
    
            @ParameterizedTest
            @MethodSource("source")
            void shouldDoSomeTests(String testCase) {
                System.out.println("Test1Cases: Doing parametrized tests: " + testCase);
            }
    
            Stream<Arguments> source() {
                return Stream.of(
                    Arguments.of("first source param!"),
                    Arguments.of("second source param!"),
                    Arguments.of("third source param!")
                );
            }
        }
    
        @Nested
        @TestInstance(TestInstance.Lifecycle.PER_CLASS)
        class Test2Cases {
    
            @BeforeAll
            void setUpForTest2() {
                System.out.println("Test2Cases: setting up things!");
            }
    
            @AfterAll
            void tearDownForTest2() {
                System.out.println("Test2Cases: tear down things!");
            }
    
            @ParameterizedTest
            @MethodSource("source")
            void shouldDoSomeTests(String testCase) {
                System.out.println("Test2Cases: Doing parametrized tests: " + testCase);
            }
    
            Stream<Arguments> source() {
                return Stream.of(
                    Arguments.of("first source param!"),
                    Arguments.of("second source param!"),
                    Arguments.of("third source param!")
                );
            }
        }
    }
    

    The output in this case was:

    Test2Cases: setting up things!
    Test2Cases: Doing parametrized tests: first source param!
    Test2Cases: Doing parametrized tests: second source param!
    Test2Cases: Doing parametrized tests: third source param!
    Test2Cases: tear down things!
    Test1Cases: setting up things!
    Test1Cases: Doing parametrized tests: first source param!
    Test1Cases: Doing parametrized tests: second source param!
    Test1Cases: Doing parametrized tests: third source param!
    Test1Cases: tear down things!