Les tests effectués sous JUnit 4 mais pas JUnit 5 - Compile propre, mais 0 exécuter des tests


Basil Bourque:

Tout le monde peut facilement reproduire ce problème en quelques minutes.

Basic Maven quickstartprojet

Avec IntelliJ 2018,3 et Maven 3.6.0, je crée un tout nouveau projet en utilisant l'archétype Maven maven-archetype-quickstartversion 1.4.

entrez la description d'image ici

Java 11

Dans le fichier POM du nouveau projet, je change les propriétés pour maven.compiler.sourceet maven.compiler.target1,7 à 11, pour Java 11.0.2 Je suis actuellement à l' aide, le zoulou de Azul Systems .

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <maven.compiler.source>11</maven.compiler.source>
  <maven.compiler.target>11</maven.compiler.target>
</properties>

Sur le panneau de Maven IntelliJ, je lance les cleanet installévénements du cycle de vie.

entrez la description d'image ici

pistes d'essai dans JUnit 4

As part of install, the tests are run. This quickstart archetype comes with one single test that asserts true.

entrez la description d'image ici

The results appear in the Run panel of IntelliJ.

[INFO] Running work.basil.example.AppTest

[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.026 s - in work.basil.example.AppTest

So I know the test executed.

JUnit 5, not 4

This is all good. Now let's upgrade to JUnit 5, to see the problem.

In the POM, I change the JUnit dependency from this:

<dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
  </dependency>
</dependencies>

…to this:

<dependencies>
  <!--JUnit 5-->
  <dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.3.2</version>
    <scope>test</scope>
  </dependency>
</dependencies>

Jupiter imports (no vintage tests)

The compiler complains about my AppTest.java file. So I change the import statements there to use the jupiter packages. I only want to run JUnit 5 tests in my new greedfield project, with no need for vintage JUnit 4 tests. So the imports change from this:

import static org.junit.Assert.assertTrue;
import org.junit.Test;

…to this:

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;

Then I execute the Maven > Lifecycle > clean & install.

…and voilà, the problem: Our test is not executed. The report seen in the Run panel of IntelliJ:

[INFO] Running work.basil.example.AppTest

[INFO] Tests run: 0, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.003 s - in work.basil.example.AppTest

➥ Why does JUnit 5 fail to run the very same test that JUnit 4 happily ran?

Update surefire plugin

I suspect the Maven Surefire Plugin needs to be updated. So in the POM I change this:

<plugin>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.22.1</version>
</plugin>

…to this:

<plugin>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>3.0.0-M3</version>
</plugin>

Another clean & install. But no better, still runs 0 tests.

[INFO] Running work.basil.example.AppTest

[INFO] Tests run: 0, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.004 s - in work.basil.example.AppTest

Entire POM

Here is my entire POM file.

<?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">
  <modelVersion>4.0.0</modelVersion>

  <groupId>work.basil.example</groupId>
  <artifactId>tester</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>tester</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>

  <dependencies>
    <!--JUnit 5-->
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>5.3.2</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>3.0.0-M3</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

JUnit libraries

After doing a Maven clean & install, two JUnit libraries appear: junit-jupiter-api and junit-platform-commons.

entrez la description d'image ici

Other versions of JUnit 5

I tried the following versions in my junit-jupiter-api dependency:

  • 5.0.0-M1
  • 5.1.1
  • 5.3.0
  • 5.3.2
  • 5.4.0-M1

On each attempt, I ran a Maven clean & install. No better. Each of those versions reported Tests run: 0.

Do not blame maven-archetype-quickstart

I actually discovered this problem in a much different project using an entirely different Maven archetype.

To nail down this buggy JUnit 5 behavior, I tried a new fresh project using the very simple maven-archetype-quickstart. I found the very same behavior: Everything compiles, the test harness in running, but no tests are executed under JUnit 5.

Basil Bourque :

tl;dr

For JUnit 5 version 5.4.0-M1 or later, specify the new single Maven artifact junit-jupiter “Aggregator” in your POM.

<!--JUnit 5-->
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.4.0-M1</version>
</dependency>

For earlier versions, specify at least these two artifacts: junit-jupiter-api & junit-jupiter-engine.

JUnit 5 yokes multiple testing frameworks

From what I can gather, JUnit 5 has been re-architected to be a yoke for multiple testing frameworks. These testing systems include JUnit 4 “vintage” tests, the new JUnit 5 tests (new syntax for tests, with new annotations & methods), and others such as Specsy, Spek, Cucumber, Drools Scenario, jqwik, and more that implement the TestEngine interface.

Apparently the junit-jupiter-api artifact is only the outer yoke. You must also specify one or more TestEngine implementations to actually run tests. For example, to run the vintage JUnit 4 tests, you need the VintageTestEngine implementations, or to run JUNit 5 tests you need the JupiterTestEngine implementation.

So to run your JUnit 5 tests, you must specify a JupiterTestEngine implementation in your Maven POM with the junit-jupiter-engine artifact.

See the JUnit 5 manual, specifically the section Configuring Test Engines.

See this presentation by Marc Philipp, with a diagram showing JUnit 5 as a platform having (A) a core for IDE/build tools with (B) pluggable test-writing frameworks for programmers authoring tests.

junit-jupiter-engine

As seen on this sample, add a second JUnit-related dependency for the JUNit Jupiter Engine. The documentation for this artifact says simply: “JUnit Jupiter test engine implementation, only required at runtime.”.

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

Simply adding that one dependency to the project shown in your Question will see your tests run.

[INFO] Running work.basil.example.AppTest

[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.004 s - in work.basil.example.AppTest


junit-jupiter-params

That same sample shows also a third JUnit dependency, for JUnit Jupiter Params. While not needed to make your example test run, it may serve other purposes. Apparently related to Parameterized Tests.

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-params</artifactId>
    <version>5.4.0-M1</version>
    <scope>test</scope>
</dependency>

That makes a total of 3 JUnit dependencies.

<!--JUnit 5-->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.4.0-M1</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-params</artifactId>
    <version>5.4.0-M1</version>
    <scope>test</scope>
</dependency>

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

Votre même fichier POM, maintenant mis à jour tous les trois de ces dépendances JUnit.

<?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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>work.basil.example</groupId>
    <artifactId>tester</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>tester</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>

        <!--JUnit 5-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.4.0-M1</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>5.4.0-M1</version>
            <scope>test</scope>
        </dependency>

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

    </dependencies>

    <build>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>3.0.0-M3</version>
                </plugin>
                <plugin>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
                <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
                <plugin>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>3.7.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-project-info-reports-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

junit-jupiter artefact

Version 5.4.0 de JUnit 5 apporte un nouvel artefact Maven, junit-jupiterintitulé JUnit Jupiter (Aggregator) . Le mot « aggrégateur * fait apparemment référence à ce regroupement quelques - unes des JUnit 5 objets couramment utilisés dans Maven, pour notre confort de programmation.

L' ajout de ce seul dependencydans votre POM vous obtient 8 bibliothèques dans votre projet.

<!--JUnit 5-->
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.4.0-M1</version>
</dependency>

Capture d'écran de vitres IntelliJ pour la structure du projet et le contenu du fichier POM, où une dépendance unique pour <code> JUnit-jupiter </ code> ajoute huit bibliothèques à votre projet, il vous suffit d'exécuter des tests JUnit 5.

Articles connexes