Search code examples
javaunit-testingjunitjunit5parameterized-tests

Junit5 Parameterized Test LifeCycle. why @BeforeAll and static block run after all the tests


I am posting a simple code below, why does @BeforeAll annotated method and static block run after the Parameterized tests? How do I register a common object or Database connection in this case before loading the Parameterized test in Junit5 or leverage the functionality of @BeforeAll or static block. (FYI: The equivalent code for Parameterized test in Junit4 runs static block before all the tests. But not the @BeforeClass annotated method.)

package com.something;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;


public class Example {
    MathUtils utils;

    static{
        System.out.println("Static Block------");
    }

    @BeforeAll
    static void beforeAllInit(){
        System.out.println("This will run Before all tests");
    }

    @BeforeEach //fresh instance before each test method
    void Init(){
        utils = new MathUtils();
        System.out.println("utils init()");
    }

    @AfterEach
    void cleanup(){
        System.out.println("Cleaning Up...");
    }

    //@Test
    @ParameterizedTest
    @CsvSource(value={"1,2,3","10,10,20","5,9,14"})
    void testAdd(int num1, int num2, int exp){
        //MathUtils utils = new MathUtils();
        //int exp = 3;
        int actual = utils.add(num1,num2);
        assertEquals(exp,actual,"Adding two numbers");
    }

    @ParameterizedTest
    @MethodSource("createDataCollection")
    void testMethod(ReadJson rj) {
        assertNotNull(rj);
    }

    public Stream<ReadJson> createDataCollection() {
        //beforeAllInit();

        final List<ReadJson> testInputs = new ArrayList<>();

        testInputs.add(new ReadJson("one","something","Miami","ABC"));
        testInputs.add(new ReadJson("two","something","New York","ABC"));
        testInputs.add(new ReadJson("three","something","Redlands","ABC"));

        return testInputs.stream();
    }

}

Output

utils init()

Cleaning Up...

utils init()

Cleaning Up...

utils init()

Cleaning Up...

Static Block------

This will run Before all tests

Process finished with exit code 0


Solution

  • Cannot reproduce. The following test file:

    package com.example;
    
    import org.junit.jupiter.api.AfterAll;
    import org.junit.jupiter.api.AfterEach;
    import org.junit.jupiter.api.BeforeAll;
    import org.junit.jupiter.api.BeforeEach;
    import org.junit.jupiter.params.ParameterizedTest;
    import org.junit.jupiter.params.provider.CsvSource;
    
    import static org.junit.jupiter.api.Assertions.assertEquals;
    
    class JUnitTests {
    
      static {
        System.out.println("Static initializer...");
      }
    
      @BeforeAll
      static void beforeAll() {
        System.out.println("Before all...");
      }
    
      @BeforeEach
      void beforeEach() {
        System.out.println("Before each...");
      }
    
      @ParameterizedTest
      @CsvSource(value = {"5,5,10", "2,3,5"})
      void parameterizedTest(int x, int y, int r) {
        System.out.printf("Parameterized test (%d, %d, %d)...%n", x, y, r);
        assertEquals(r, x + y, () -> String.format("%d + %d expected to equal %d", x, y, r));
      }
    
      @AfterEach
      void afterEach() {
        System.out.println("After each...");
      }
    
      @AfterAll
      static void afterAll() {
        System.out.println("After all...");
      }
    }
    

    Compiled and executed with the following Gradle build script:

    plugins {
        java
    }
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        testImplementation("org.junit.jupiter:junit-jupiter:5.8.2")
    }
    
    tasks.test {
        useJUnitPlatform()
        testLogging {
            showStandardStreams = true
        }
    }
    

    Gives the following output:

    > Task :test
    
    JUnitTests STANDARD_OUT
        Static initializer...
        Before all...
    
    JUnitTests > parameterizedTest(int, int, int) > com.example.JUnitTests.parameterizedTest(int, int, int)[1] STANDARD_OUT
        Before each...
        Parameterized test (5, 5, 10)...
        After each...
    
    JUnitTests > parameterizedTest(int, int, int) > com.example.JUnitTests.parameterizedTest(int, int, int)[2] STANDARD_OUT
        Before each...
        Parameterized test (2, 3, 5)...
        After each...
    
    JUnitTests STANDARD_OUT
        After all...
    
    BUILD SUCCESSFUL in 3s
    3 actionable tasks: 3 executed
    

    As you can see, everything is executed in the expected order.