1

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

  • It should be impossible for the static initializer block to run after any method in the class is invoked, just by virtue of how Java works. I also cannot reproduce your output with JUnit 5.8.2. – Slaw Jun 16 '22 at 00:37
  • its something with loading the source data which happens before class initialization, but cannot understand what happens with static or @BeforeAll and how do we prevent that. – Achint Jain Jun 16 '22 at 02:54
  • @Slaw Also what do you mean by reproduce my output. You run the code and it is different from what I have shown above? – Achint Jain Jun 16 '22 at 02:58
  • Can you strip away all external code (MathUtil and ReadJson) and see what happens then? – johanneslink Jun 16 '22 at 05:26
  • Well, I can't run your code directly, as you have types which I don't have access to. But yes, when I tried it, my output was: static initializer -> before all -> before each -> parameterized test -> after each -> after all. As expected. – Slaw Jun 16 '22 at 05:34
  • "_its something with loading the source data which happens before class initialization_" – Maybe? But that doesn't explain how you're seeing the static initializer invoked after any test method is invoked, let alone all of the test methods. A class must be initialized before any of its methods can be invoked. Executing the tests involves executing said methods. Static initializers are executed during class initialization. Hence my confusion regarding your output. – Slaw Jun 16 '22 at 05:44
  • @Slaw can you send me the code you wrote when you got : static initializer -> before all -> before each -> parameterized test -> after each -> after all – Achint Jain Jun 16 '22 at 16:42
  • Okay, so after you comments, I made a static count variable to be incremented from each block and this is what I found below. Whats with the sequence? I shouldnt be bothered about that right? Seem like it was leading. `utils init() beforeeach 3 parameterized func 4 Cleaning Up... aftereach 5 utils init() beforeeach 6 parameterized func 7 Cleaning Up... aftereach 8 utils init() beforeeach 9 parameterized func 10 Cleaning Up... aftereach 11 Static Block------ static 1 This will run Before all tests beforeall 2` – Achint Jain Jun 16 '22 at 17:24
  • It happens for me when I am executing tests by the means of IntelliJ IDEA (green 'Play' button). When I using terminal with the console command, the output is as expected. – zer_ik Apr 17 '23 at 11:45

1 Answers1

2

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.

Slaw
  • 37,820
  • 8
  • 53
  • 80
  • Thank you, I think I figured out the issue, the output was misleading me in the order of execution. However everything worked as you stated. – Achint Jain Jun 16 '22 at 23:20