'Preventing the use of junit4 libraries in a project

There is an existing software project, developed and maintained by several developers. The IDE is IntelliJ, the build tool is Maven. The project has had both JUnit 4 and JUnit 5 tests. We want to refactor and use only JUnit 5 from now.

The problem is that code completion from the IDE still offers both JUnit 4 and JUnit 5, and devs might accidentally use them, e.g. org.junit.Assert.assertTrue instead of org.junit.jupiter.api.Assertions.assertTrue.

Is there an elegant, automated way to detect the use of JUnit 4 classes as early as possible?



Solution 1:[1]

There are a few options once all the tests are converted from JUnit 4 to JUnit 5.

The most straightforward option is to exclude JUnit 4 from the classpath. Depending on what libraries are being used, some dependency-level exclusions might need to be added to avoid transitively pulling in JUnit 4. This setup will cause the build to fail at the compilation stage if any JUnit 4 imports are in use. It will also generally prevent the IDE from providing JUnit 4 classes as auto-completion options.

This option may not be available if another testing library requires JUnit 4. For instance, the Testcontainers library still requires JUnit 4 to be on the classpath, even if the tests themselves are written in JUnit 5 (testcontainers-java#970). In this case, one option is to write a Checkstyle rule to disallow non-Jupiter JUnit imports, and to have the build fail when Checkstyle failures occur.

The relevant Checkstyle config:

<module name="IllegalImport">
    <property name="regexp" value="true"/>
    <!-- Reject any org.junit import that's not also org.junit.jupiter: -->
    <property name="illegalClasses" value="^org\.junit\.(?!jupiter\.).+"/>
</module>

Solution 2:[2]

  1. If junit 4.x is not needed on classpath, you can remove it from classpath and add to the banned dependencies list of maven-enforcer-plugin:

                 <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-enforcer-plugin</artifactId>
                 <version>${maven-enforcer-plugin.version}</version>
                 <executions>
                     <execution>
                         <id>enforce</id>
                         <configuration>
                             <rules>
                                 <bannedDependencies>
                                     <excludes>
                                         <exclude>junit:junit</exclude>
    
                                     </excludes>
                                 </bannedDependencies>
                             </rules>
                         </configuration>
                         <goals>
                             <goal>enforce</goal>
                         </goals>
                     </execution>
                 </executions>
             </plugin>
    
  2. if junit 4.x is required to be on classpath (e.g. testcontainers still depend on it), but you do not want other people to write tests using it -- use restrict-imports-enforcer-rule:

                 <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-enforcer-plugin</artifactId>
                 <version>${maven-enforcer-plugin.version}</version>
                 <dependencies>
                     <dependency>
                         <groupId>de.skuzzle.enforcer</groupId>
                         <artifactId>restrict-imports-enforcer-rule</artifactId>
                         <version>2.0.0</version>
                     </dependency>
                 </dependencies>
                 <executions>
                     <execution>
                         <id>enforce</id>
                         <configuration>
    
                             <rules>
                                 <RestrictImports>
                                     <reason>Please instead use Junit 5.</reason>
                                     <bannedImports>
                                         <bannedImport>org.junit.Test</bannedImport>
                                         <bannedImport>org.junit.runner.RunWith</bannedImport>
                                         <bannedImport>org.junit.Before</bannedImport>
                                         <bannedImport>org.junit.After</bannedImport>
                                     </bannedImports>
                                 </RestrictImports>
                             </rules>
                         </configuration>
                         <goals>
                             <goal>enforce</goal>
                         </goals>
                     </execution>
                 </executions>
             </plugin>
    

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Anastasiia Smirnova