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.

Rahul B
  • 132
  • 1
  • 1
  • 11
Luca
  • 300
  • 1
  • 4
  • 11
  • 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. – davidxxx Jul 17 '18 at 13:23
  • Added every thing you said, but did not spesificly configure the surefile plugin – Luca Jul 17 '18 at 13:39
  • So the problem is there. Check out that : https://junit.org/junit5/docs/current/user-guide/#running-tests-build-maven – davidxxx Jul 17 '18 at 13:51
  • 1
    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. – Geert-Jan Hut Apr 01 '19 at 05:59

3 Answers3

27

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

Johnson
  • 306
  • 1
  • 15
davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • that fixed the problem thanks :D I only needed to add that to the pom of my test Module. – Luca Jul 17 '18 at 13:59
  • 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. – davidxxx Jul 17 '18 at 14:13
  • 3
    Time flies by... Maven Surefire 2.22.0 now supports JUnit 5 out of the box. – Marc Philipp Jul 17 '18 at 17:21
  • 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! – Kim Zeevaarders Feb 04 '20 at 07:44
  • 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. – Johnson Oct 28 '20 at 09:43
5

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
khmarbaise
  • 92,914
  • 28
  • 189
  • 235
  • 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 :) – AJPerez Feb 13 '23 at 07:13
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