1

I have both JUnit4 and JUnit5 tests in my project. The problem is that when I run mvn clean install the JUnit4 tests are run twice (JUnit5 tests run fine and once only).

I have the following surefire-plugin configuration (showing only relevant dependencies) in my parent project pom

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.22.2</version>
  <configuration>
    <threadCount>1</threadCount>
    <properties>
      <property>
        <name>junit</name>
        <value>false</value>
      </property>
    </properties>
  </configuration>
  <dependencies>
    <dependency>
      <groupId>org.apache.maven.surefire</groupId>
      <artifactId>surefire-testng</artifactId>
      <version>2.22.2</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven.surefire</groupId>
      <artifactId>surefire-junit-platform</artifactId>
      <version>2.22.2</version>
    </dependency>
  </dependencies>
</plugin>
...
...
<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter-engine</artifactId>
  <version>5.6.2</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.junit.vintage</groupId>
  <artifactId>junit-vintage-engine</artifactId>
  <version>5.6.2</version>
  <scope>test</scope>
</dependency>
<dependency>
  <!-- needed for https://youtrack.jetbrains.com/issue/IDEA-231927?_ga=2.101965186.223349104.1602977709-1646014256.1600106493 -->
  <groupId>org.junit.platform</groupId>
  <artifactId>junit-platform-launcher</artifactId>
  <version>1.6.2</version>
  <scope>test</scope>
</dependency>

I replicated the above surefire-plugin in the child project as well to make sure it does not get overridden by anything. But still, the JUnit4 tests are run twice.

Following is the surefire-plugin portion in the effective pom -

<plugin>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.22.2</version>
  <configuration>
    <threadCount>1</threadCount>
    <properties>
      <property>
        <name>junit</name>
        <value>false</value>
      </property>
    </properties>
  </configuration>
  <dependencies>
    <dependency>
      <groupId>org.apache.maven.surefire</groupId>
      <artifactId>surefire-testng</artifactId>
      <version>2.22.2</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven.surefire</groupId>
      <artifactId>surefire-junit-platform</artifactId>
      <version>2.22.2</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven.surefire</groupId>
      <artifactId>surefire-junit47</artifactId>
      <version>2.19.1</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
</plugin

On doing some debugging with -X option I think the reason is because surefire-junit47 also gets added in the providers for surefire-plugin, surefire-junit-platform runs the junit4 tests once and they are run again by surefire-junit47 provider. If that is a probable reason then how can I prevent this from getting added to surefire-plugin dependencies? I tried <classpathDependencyExcludes> but that didn't help and the effective pom still contained surefire-junit47.

Also is there any way to avoid JUnit4 running twice even with having both providers (surefire-junit47 and surefire-junit-platform)?

---------- Update ------------

I also have set the junit property to false in the configuration for surefire to prevent testng provider running the junit tests (as suggested here). But still, I am getting two runs of JUnit4 tests. My guess is that somehow surefire-junit47(which is getting added mysteriously) and surefire-junit-platform are acting weird together to cause duplicated runs.

---------- Update ------------

The actual problem turns out that my project is inheriting a parent pom which has declared a dependency surefire-junit47 in surefire-plugin. So effectively my project has both surefire-junit-platform and surefire-junit47 which results in dual runs of JUnit4 tests.

Harry
  • 321
  • 4
  • 13

1 Answers1

2

I was able to reproduce your problem. You are running into a situation described here:

TestNG 6.5.1 and higher provides support to run TestNG and JUnit 4.x in current Maven project. (...)

You may want to run two providers, e.g. surefire-junit47 and surefire-testng, and avoid running JUnit tests within surefire-testng provider by setting property junit=false.

So please change your Surefire plugin configuration to:

<configuration>
  <threadCount>1</threadCount>
  <properties>
    <!-- Avoid running JUnit 4 tests in TestNG engine -->
    <property>
      <name>junit</name>
      <value>false</value>
    </property>
  </properties>
</configuration>

Update: How to (pseudo) exclude a direct Maven plugin dependency:

Okay, FWIW I came up with a hacky way to "exclude" a dependency by overriding it with a dummy.

First you add a module to your project's root POM, but without specifying the root POM as its parent. Just make sure the module is built in the same reactor. Alternatively, you can also create a separate project for it and make sure its resulting artifact is in your company's repository.

The module POM looks like this:

<?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>org.apache.maven.surefire</groupId>
  <artifactId>surefire-junit47</artifactId>
  <version>dummy</version>
</project>

In your child POM where you wish to deactivate the JUnit 4.7 engine in favour of running your JUnit 4 tests on the JUnit 5 platform, you can do something like this:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>${maven-surefire.version}</version>
  <configuration>
    <threadCount>1</threadCount>
    <properties>
      <!-- Avoid running JUnit 4 tests in TestNG engine -->
      <property>
        <name>junit</name>
        <value>false</value>
      </property>
    </properties>
  </configuration>
  <dependencies>
    <dependency>
      <!-- Deactivate JUnit 4.7 engine by overriding it with an empty dummy -->
      <groupId>org.apache.maven.surefire</groupId>
      <artifactId>surefire-junit47</artifactId>
      <version>dummy</version>
    </dependency>
  </dependencies>
</plugin>

<!-- (...) -->

<dependencies>
  <dependency>
    <groupId>org.apache.maven.surefire</groupId>
    <artifactId>surefire-junit47</artifactId>
    <version>dummy</version>
  </dependency>
</dependencies>

This is super ugly and I would still recommend refactoring the parent POM, if possible. Anyway, it works. Now your JUnit 4 tests only run once, i.e. inside the JUnit 5 platform alongside JUnit 5 tests, Spock 2.0 tests or what have you.


Update 2: After you provided an MCVE on GitHub, I sent you a pull request implementing exactly the workaround I mentioned in the previous update. The important commit is this one.

kriegaex
  • 63,017
  • 15
  • 111
  • 202
  • hi @kriegaex, thanks for reproducing my problem! Actually, I already have that property set in my pom file and I am still getting two runs of JUnit4. I have updated my question to include this property in updated pom.xml as well. – Harry Oct 18 '20 at 05:33
  • Then please provide an [MCVE](https://stackoverflow.com/help/mcve) for me to reproduce the problem. Condense your project into the smallest sample still reproducing the problem, removing everything irrelevant. Then publish it on GitHub and send me the link. I cannot debug what I cannot see. The information provided by you seems relevant to you, but the problem must hide in the part of your project you did **not** show yet. I have several ideas what might go wrong, but I hate to speculate blindly. I already wasted time by writing an unnecessary answer because you were hiding information. – kriegaex Oct 18 '20 at 05:38
  • thanks @kriegaex, I was trying to produce a MCVE and it helped me debug the problem as well. I found that the parent pom for my project has already defined `surefire-junit47` depedency in the surefire-plugin. Maven merges that with the surfire-plugin in my pom which results in both surefire-junit47 and surefire-junit-platform in my project's pom (which causes dual runs). – Harry Oct 19 '20 at 01:17
  • is there a way to completely override the dependencies declared in the parent pom for surefire-plugin? I was looking at `combine.self="override"` but it seems that only applies to configurations. – Harry Oct 19 '20 at 01:18
  • Like I said, I like to analyse, not speculate. My answer is correct for the case you asked about. If your real case is more complex, please show it like I asked you to. I cannot say anything intelligent about a set of POMs I cannot see. I also do not feel so inclined to answer new questions asked in comments, just because you seem to think you should solve the problem in a specific way. This bears the danger of being an instance of the [XY problem](https://meta.stackexchange.com/a/66378/309898). So please show me yours, then I will show you mine. – kriegaex Oct 19 '20 at 01:39
  • As for your question, there is no way to exclude a direct plugin dependency as of today (Maven 3.x), see [issue MNG-6222](https://issues.apache.org/jira/browse/MNG-6222). If you have access to the parent POM, you should refactor it and all projects using it as a parent. If that is not possible you could also create a new, similar parent POM for your current project. In general, it makes sense to preconfigure plugins in such a way that they allow for adding things, not to get users stuck wishing to remove things. – kriegaex Oct 19 '20 at 02:00
  • Please note my update in which I am showing a hacky way to deactivate a direct Maven plugin dependency. – kriegaex Oct 19 '20 at 02:15
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/223257/discussion-between-harry-and-kriegaex). – Harry Oct 19 '20 at 04:53
  • **Update 2:** After you provided an [MCVE on GitHub](https://github.com/haverma/junit-test), I sent you a [pull request](https://github.com/haverma/junit-test/pull/1) implementing exactly the workaround I mentioned in the previous update. The important commit is [this one](https://github.com/haverma/junit-test/pull/1/commits/d7669d30f264d3b4862462d6406bbd3cc9f4d9f4). – kriegaex Oct 19 '20 at 06:01