Maven does not run @BeforeEach Methods while running
Asked Answered
H

3

19

i have a test Class lets call it TestSomething, and a Test Object lets call this one SomeObject.

Now i need this Object in every Single Test new this means that i have in my Code a @BeforeEach that loads this Object in a Field:

import me.test.SomeObject;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class TestSomething {
    private SomeObject someObject;

    @BeforeEach
    public void load() {
        someObject = new SomeObject();
    }

    @Test
    public void test1() {
        boolean result = someObject.checkForSomething();
        Assertions.assertEquals(true, result);
    }

    @Test
    public void test2() {
        boolean result = someObject.checkForSomethingElse();
        Assertions.assertEquals(false, result);
    }

pom.xml from the Test Module:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <parent>
    <artifactId>test</artifactId>
    <groupId>me.test</groupId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>


  <properties>
    <projectVersion>1.0.0</projectVersion>
    <maven.deploy.skip>false</maven.deploy.skip>
  </properties>


  <artifactId>Tests</artifactId>
  <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>5.0.3</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>me.test</groupId>
      <artifactId>project</artifactId>
      <version>1.0-SNAPSHOT</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

not sure if it is relevant, but the Object SomeObject is in a separate Module, and the Test Module has a Dependency on that Module with Scope test. (i also tried provided and compile)

So now if i Run this Tests in InteliJ they Work just Fine. but now if i try to Build my Project the Tests Fail, with NullPointerExceptions because someObject is null.

Now the Test work of i call the Method load() in every Test, but that is not exactly what i want.

Harken answered 17/7, 2018 at 13:14 Comment(4)
Show your maven configuration. Maybe, you didn't configure the maven-surefire-plugin as it should. Please show also your imports in the test class.Interpolate
Added every thing you said, but did not spesificly configure the surefile pluginHarken
So the problem is there. Check out that : junit.org/junit5/docs/current/user-guide/…Interpolate
The surefire plugin will still not pickup the @BeforeEach annotated methods when you forget to add the junit-jupiter-engine artifact as a dependency. IDE's are content when you have the junit-jupiter-api artifact added, but the surefire plugin will revert back to a junit3 runner when you don't specify the engine also. Surefire will still run your tests, even if the @Test annotation is from the org.junit.jupiter.api package. However, the @BeforeEach (and @AfterEach etc.) annotated methods will not be executed.Vashti
I
28

By default Maven will not run the test with the Jupiter engine as

In order to have Maven Surefire run any tests at all, a TestEngine implementation must be added to the runtime classpath.

And this is not present by default.
So to enable it you have to configure the maven-surefire-plugin that runs the unit tests as documented in the Jupiter documentation :

UPDATE (28.10.2020):

Since version 2.22.0, you only have to specify a test dependency on the desired junit engine. Failing to do so, will also result in the behavior described in the question.

<dependencies>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.4.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Keeping the original answer as a reference, before version 2.22.0 the solution was:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.21.0</version>
            <dependencies>
            <dependency>
                <groupId>org.junit.platform</groupId>
                <artifactId>junit-platform-surefire-provider</artifactId>
                <version>1.2.0</version>
            </dependency>
            <dependency>
                <groupId>org.junit.jupiter</groupId>
                <artifactId>junit-jupiter-engine</artifactId>
                <version>5.2.0</version>
            </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

Whatever the issue is not necessarily easy to spot because Maven uses a runner that is able to run the Jupiter tests but didn't manage to execute the hook methods...

As a hint : to know whether the JUnit 5 runner is launched you can execute the tests with the verbose flag such as : mvn test -X.
If the Jupiter runner is used, you should find lines that look like :

[DEBUG] Surefire report directory: ...\target\surefire-reports

[DEBUG] Using configured provider org.junit.platform.surefire.provider.JUnitPlatformProvider

Interpolate answered 17/7, 2018 at 13:52 Comment(5)
that fixed the problem thanks :D I only needed to add that to the pom of my test Module.Harken
You are very welcome :) JUnit 5 is not the standard yet. So maven doesn't include it by default. But in few years, it should change I hope ! I updated the answer. This may help.Interpolate
Time flies by... Maven Surefire 2.22.0 now supports JUnit 5 out of the box.Colored
Just wanted to add that if you use Spring Boot you must exclude the junit-vintage-engine library from the spring-boot-starter-test dependency. Because we were using some junit 4 annotations in our test somehow manve ran the tests with the junit4 runner instead of junit 5. After excluding the dependency and refactoring all junit4 annotations to junit5 it worked!Loth
As @MarcPhilipp already mentioned, version 2.22.0 supports JUnit without the need of junit-platform-surefire-provider. You still have to include test dependencies to the correct test engine. I updated the answer accordingly.Proboscis
W
7

The first you need to do is to add a dependency like this:

<dependencies>
    [...]
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.8.2</version>
        <scope>test</scope>
    </dependency>
    [...]
</dependencies>

The next thing is to use the most recent version of maven-surefire-plugin/maven-failsafe-plugin like this:

<build>
    <plugins>
        ...
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.22.2</version>
            <configuration>
                <excludes>
                    <exclude>some test to exclude here</exclude>
                </excludes>
            </configuration>
        </plugin>
    </plugins>
</build>

Starting with version 2.22.2 surefire supports JUnit 5...

Update:

  • Use most recent version of maven-surefire/failsafe-plugin
Wary answered 18/7, 2018 at 10:15 Comment(1)
Thanks, this solved my issue. My SpringBoot app was already using the junit-jupiter-engine, but with an older surefire plugin. Forcing it to v2.22.2 did the trick :)Police
T
2

maven-surefire-plugin by default takes all test classes which have the pattern *Test.java, in your case you should rename the class SomethingTest and it should be OK

https://maven.apache.org/surefire/maven-surefire-plugin/examples/inclusion-exclusion.html

Topheavy answered 17/7, 2018 at 13:29 Comment(1)
well it runs the test but they just Fail, see: hastebin.com/makemirifu.cssHarken

© 2022 - 2024 — McMap. All rights reserved.