Using Testcontainers without JUnit4 dependency

In this blog post I will explain how to run integration test with Testcontainers without using JUnit4 dependency.

Testcontainers has support for JUnit5 but it has dependency on JUnit4 libraries.

Java frameworks either new or old frameworks with newer versions are not including the JUnit4 dependencies.

For example, Spring Boot version 2.4.2 completely removed JUnit4 dependency, so If your application uses JUnit4 testcases you need to include corresponding libraries.

If your application has JUnit5 test cases and you want to explicitly exclude the JUnit4 dependency from all your dependencies to make sure that people do not use it accidentally or out of habit then you need to do some changes as Testcontainers has dependency on JUnit4 classes.

Testcontainers GenericContainer class depends on class from Junit4. If you remove JUnit4 dependency , you will face Compile/Runtime error.

Let’s run the application by removing the JUnit4 library.

To remove JUnit4 library from Testcontainers , use following snippet in pom.xml

<dependency> <groupId>org.testcontainers</groupId> <artifactId>junit-jupiter</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>junit</groupId> <artifactId>junit</artifactId> </exclusion> </exclusions> </dependency>
Code language: HTML, XML (xml)

If you are using Spring Boot version < 2.4.2, you need to remove JUnit4 library from spring-boot-starter-test dependency

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency>
Code language: Java (java)

If we run the integration tests with below command

mvn clean verify
Code language: Shell Session (shell)

You will see following errors

cannot access org.junit.rules.TestRule

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:testCompile (default-testCompile) on project springboot-testcontainers-example3: Compilation failure [ERROR] cannot access org.junit.rules.TestRule
Code language: Java (java)

java.lang.NoClassDefFoundError: org/junit/runners/model/Statement

java.lang.NoClassDefFoundError: org/junit/runners/model/Statement
Code language: Java (java)

java.lang.NoClassDefFoundError: org/junit/rules/ExternalResource

You might also see below error message based on the Testcontainers module added

java.lang.NoClassDefFoundError: org/junit/rules/ExternalResource
Code language: Java (java)

Solutions

Method 1) To resolve these errors you just need to add the corresponding Empty TestRule and Statement interfaces in root of test folder. Since GenericContainer doesn’t really use them unless run by JUnit 4, this hack works fine.

package org.junit.rules; @SuppressWarnings("unused") public interface TestRule { }
Code language: Java (java)

package org.junit.runners.model; @SuppressWarnings("unused") public interface Statement { }
Code language: Java (java)

Method 2) If you do not want to create these interfaces in your code, you can add following maven dependency in your application which is created for Quarkus but also works for Spring Boot based application. The library has all the required empty interface/classes.

<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-junit4-mock</artifactId> <version>2.11.2.Final</version> </dependency>
Code language: Java (java)

Similar Posts