GenericContainer run from Jupiter tests shouldn't require JUnit 4.x library on runtime classpath
bmuschko opened this issue Β· 63 comments
I tried out the JUnit 5 support using the following build script. I'd expect that TestContainers doesn't require the JUnit 4.x library. As you can see in the build script below, the legacy dependency has been excluded.
apply plugin: 'java-library'
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
version = '1.0'
repositories {
jcenter()
}
dependencies {
def junitJupiterVersion = '5.3.1'
testImplementation "org.junit.jupiter:junit-jupiter-api:$junitJupiterVersion"
testImplementation "org.junit.jupiter:junit-jupiter-params:$junitJupiterVersion"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitJupiterVersion"
testImplementation 'org.testcontainers:junit-jupiter:1.10.1'
}
// IMHO shouldn't be required
configurations.all {
exclude group: 'junit', module: 'junit'
}
tasks.withType(Test) {
useJUnitPlatform()
}
In my test case, I am creating a GenericContainer
.
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
@Testcontainers
public class TestContainerJunit5Test {
@Container
private GenericContainer appContainer = new GenericContainer();
@Test
void tryItOut() {
// do something
}
}
At runtime I get the following exception. My guess is that GenericContainer
still uses JUnit 4.x classes.
java.lang.NoClassDefFoundError: org/junit/rules/TestRule
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2583)
at java.lang.Class.getDeclaredFields(Class.java:1916)
at org.junit.platform.commons.util.ReflectionUtils.getDeclaredFields(ReflectionUtils.java:1106)
at org.junit.platform.commons.util.ReflectionUtils.findAllFieldsInHierarchy(ReflectionUtils.java:886)
at org.junit.platform.commons.util.ReflectionUtils.findFields(ReflectionUtils.java:874)
at org.junit.platform.commons.util.AnnotationUtils.findAnnotatedFields(AnnotationUtils.java:320)
at org.junit.platform.commons.util.AnnotationUtils.findAnnotatedFields(AnnotationUtils.java:297)
at org.junit.jupiter.engine.descriptor.ExtensionUtils.registerExtensionsFromFields(ExtensionUtils.java:92)
at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.prepare(ClassTestDescriptor.java:154)
at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.prepare(ClassTestDescriptor.java:74)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$0(NodeTestTask.java:80)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:80)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:66)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:110)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:71)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:92)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$100(JUnitPlatformTestClassProcessor.java:77)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:73)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy2.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:131)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:155)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:137)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassNotFoundException: org.junit.rules.TestRule
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 80 more
Hi @bmuschko,
We very much agree, and we do plan to remove the dependency, but it will be a breaking change and we will do it in Testcontainers 2.0.
We were planning to start 2.0 earlier but discovered a few low hanging fruits (like the JUnit 5 extension, or OkHttp transport), this is why it got delayed. But now probably is a good time to finally focus on 2.0 :)
Great, thanks for confirming. Looking forward to 2.0.
I ran into this issue as well and it's currently a blocker for me. Is there any estimated date when 2.0 will be released? Where can I find roadmap?
The product looks very promising btw :) looking forward to 2.0 as well so I can finally start using it
Sorry, we haven't updated the roadmap for quite some time π
Why exactly is it a blocker for you?
wow, that was a quick response :)
we switched to Junit5 and are explicitly excluding Junit4 from all dependencies to make sure people don't use it accidentally or out of habit
I see, makes sense for some projects.
We would love to remove this dependency rather sooner than later, however since it will be a breaking change, we haven't decided on when to actually do it yet.
Any updates on this one?
@evonier no updates since the last acknowledgement of the problem and the promise to target it for 2.x version.
Updating testcontainers from version 1.11.4 to version 1.12.0 fixed the same problem for me
Updating testcontainers from version 1.11.4 to version 1.12.0 fixed the same problem for me
But things still derive from the JUnit 4 TestRule
π€
Is there any update ? With v 1.12.5 the exclusion of junit dependency still results in class problems.
As a hint: at my work, I use a test container jdbc url for creating the datasource. And therefore, the docker container "run" creation is delegated to the test container driver itself. No explicit coding with @ClassRule
and/or @Rule
within my unit/integration tests. From that point of view, the dependency to junit4 does not make really sense to me.
With v 1.12.5 the exclusion of junit dependency still results in class problems.
You can create your wrapper maven project, exclude JUnit4 and provide necessary JUnit classes separately.
Here's a workaround if no dependency on JUnit 4 is a must: create fake TestRule
and Statement
classes under your test root. 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 {
}
and
package org.junit.runners.model;
@SuppressWarnings("unused")
public class Statement {
}
@detouched
Thanks. I also needed to include another empty class for my WebDriverContainer.
package org.junit.rules;
public class ExternalResource {
}
Was getting the following exception:
java.lang.NoClassDefFoundError: org/junit/rules/ExternalResource
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
...
at org.testcontainers.containers.Network.<clinit>(Network.java:22)
at org.testcontainers.containers.BrowserWebDriverContainer.configure(BrowserWebDriverContainer.java:158)
at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:305)
at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:300)
Is there any intention to fix this in the near future?
we switched to Junit5 and are explicitly excluding Junit4 from all dependencies to make sure people don't use it accidentally or out of habit
Same here π We also excluded all JUnit 4 dependencies to be forced to use Jupiter.
@pixelstuermer since this is not a major issue, atm we're focusing on other, bigger ones.
That said, we do plan to decouple the core from JUnit 4 in 2.0 (with probably an experimental API in 1.x that will allow the migration path), but it will take a bit of time.
@pixelstuermer since this is not a major issue, atm we're focusing on other, bigger ones.
That said, we do plan to decouple the core from JUnit 4 in 2.0 (with probably an experimental API in 1.x that will allow the migration path), but it will take a bit of time.
OK thanks. Nice to hear that you will keep an eye on this π
Any updates on this? It is really causing our team to struggle as there are junit 4 annotation but they don't work
Same here folks, I hope this issue will be addressed soon.
Migrated projects to the latest Spring Boot 2.4.2 where JUnit 4 is removed, so I hope we can get JUnit 5 support for testcontainers with JUnit 4 exluded.
Since this requires some more fundamental changes to the existing codebase and architecture, we can't give an ETA on this feature. @bsideup already outlined some aspects in this issue and further inquiries won't expedite the development or release of this feature.
Given the amount of duplicate issues asking for the same thing, I think this issue can be considered major?
@gastaldi what makes it major? Does it break anything? Or blocks some usage?
Since GenericContainer
depends on a class from JUnit 4, we can't easily remove the dependency, meaning that we either need to work on 2.0 or introduce a new API (something that we considered) that won't have said classes in the class hierarchy, so it can be excluded.
FWIW the current "problem" with JUnit 4 is that both JUnit 4 and JUnit 5 annotations are present and sometimes people use org.junit.Test
instead of Jupiter's (unless we miss some other major issues with having JUnit 4 in our dependencies)
There are workarounds (see above), there are codestyle rules that prevents the usage of org.junit.*
annotations. Given that, I struggle to agree that the issue is major, and that we should spend our (currently very reduced due to personal reasons) time on it and not on other major issues/features.
WDYT?
It introduces security issues, for one. For JUnit 5 projects, JUnit 4 dependency offers extra attack surface.
Hey @bsideup!
Since this introduces some API changes (major changes I believe) I agree this needs to be targeted to 2.0 (along with support for Podman, but that's another discussion π).
My use case is simple: we are planning to use TestContainers to bootstrap databases when running tests with Quarkus. Because our tests require JUnit 5, having the JUnit 4 JAR in the classpath may be confusing, but we can workaround it somehow.
See the full thread here: https://groups.google.com/g/quarkus-dev/c/EQpAI9kBrGk/m/URMR8OibBAAJ
@lprimak please read that CVE before using the "security issues" argument. Just having a jar on your classpath does not introduce any security issues. Plus, that CVE was about the TemporaryFolder
rule, and too permissive access that allows reading temporary files created by that rule by other users.
This is hilarious to refer to it as a security risk of having JUnit 4 as a dependency π
please read that CVE before using the "security issues" argument
oh come on now :) I am talking about attack surface, not that one particular issue.
Guys come on, the Testcontainers team are working on this in their own free time, if you really want to expedite it, then you should help contribute to the project or get your company to sponsor them.
If not, if the issue is really critical to you, you can always use the workaround by @detouched here: #970 (comment)
@gastaldi There are no plans to support Podman in 2.0 (unless you know something that I don't, e.g. some generosity by Red Hat to join us as a Gold Sponsor and push the idea forward).
As we previously communicated many times, Podman should provide an API that is compatible with Docker, as they claim they do.
My use case is simple: we are planning to use TestContainers to bootstrap databases when running tests with Quarkus.
Nice! Although I am afraid in this case even the new experimental API in 1.x won't help as you would expose the Testcontainers dependency to your users (otherwise you would just use the stub workaround), and excluding junit4 would make the end users struggle to understand why new GenericContainer
fails the compilation for them when used in Quarkus... 2.0
is closer than ever (yes, I know that I said something similar 2 years ago, lol), so this period of junit4 dependency shouldn't be long :)
Thanks @bsideup !
Yeah, I was reading the outcome of that discussion about podman after commenting in this issue and I think this API is planned for Podman 3.0 but I haven't tested yet.
BTW TestContainers is fantastic and you guys are doing an amazing job!
Keep up the good work! ππ»
May I suggest creating a "junit4-workaround" module within testcontainers that could be easily added to any projects that may need it. I can submit a PR with this.
@svpace How do you imagine such a module to be implemented if Testcontainers core classes depend on JUnit4?
shade plugin?
Basically #970 (comment) and #970 (comment). Exclude junit4 and add workaround module with the empty classes. Not a perfect solution, but I've been using this setup locally for some time without issues so far.
Quarkus users can use this dep https://mvnrepository.com/artifact/io.quarkus/quarkus-junit4-mock
Module with some empty JUnit4 classes to allow Testcontainers to run without needing to include JUnit4 on the class path
Thanks for sharing @cameronbraid ! Looks like there are no dependencies and just dummy classes based on https://github.com/quarkusio/quarkus/tree/main/core/junit4-mock so seems it would work fine for anyone to use it, even if not using Quarkus.
Unfortunately all versions are compiled for Java 11 so it wonβt work for us poor Java 8 users π
Quarkus users can use this dep https://mvnrepository.com/artifact/io.quarkus/quarkus-junit4-mock
Module with some empty JUnit4 classes to allow Testcontainers to run without needing to include JUnit4 on the class path
Hello @detouched and everyone else,
your workaround works fine for my gradle build. When I try to execute the tests with Intellij there is always coming the error below:
Supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath:
class org.testcontainers.containers.FailureDetectingExternalResource, unresolved supertypes: org.junit.rules.TestRule
Has anyone an idea how I can execute the tests with a testcontainer via IDE?
With best regards
Henni
Up. Are there any upcoming news? We're looking forward to get rid of junit4 completely in our company test dependencies. And the only one is testcontainers (which brings that legacy into our test class path).
P.S. I β€οΈ testcontainers, this library helped to move testing to another level.
Hi @bmuschko,
We very much agree, and we do plan to remove the dependency, but it will be a breaking change and we will do it in Testcontainers 2.0. We were planning to start 2.0 earlier but discovered a few low hanging fruits (like the JUnit 5 extension, or OkHttp transport), this is why it got delayed. But now probably is a good time to finally focus on 2.0 :)
More than four years have gone since that comment. Still there.
Hello @detouched and everyone else,
your workaround works fine for my gradle build. When I try to execute the tests with Intellij there is always coming the error below:
Supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath:
class org.testcontainers.containers.FailureDetectingExternalResource, unresolved supertypes: org.junit.rules.TestRuleHas anyone an idea how I can execute the tests with a testcontainer via IDE?
With best regards Henni
That happened to me when adding those classes as Kotlin code and fixed when added as Java code. I copied the following classes from JUnit 4 repository to my repository:
I had to add also org.awaitility:awaitility dependency.
Hi @bmuschko,
We very much agree, and we do plan to remove the dependency, but it will be a breaking change and we will do it in Testcontainers 2.0. We were planning to start 2.0 earlier but discovered a few low hanging fruits (like the JUnit 5 extension, or OkHttp transport), this is why it got delayed. But now probably is a good time to finally focus on 2.0 :)
Good plan! How long it will continue? Five years ago..
let's just acknowledge that testcontainers is a mediocre project where nobody cares about transitive dependencies or other minor things.
let's just acknowledge that testcontainers is a mediocre project where nobody cares about transitive dependencies or other minor things.
While above is a bit harsh, it is really regrettable that 5 years since there is absolutely no progress on this issue.
TestContainers should be on version 5 by now, but still we are "afraid" to release version 2.
Do not be afraid folks, let's move on from this and on to version 2..3.. 5...!
:( Another release of testcontainers, and yet it's not 2.0 :( :(
For reference, this has become an issue in the project I'm working on. Somehow, IntelliJ is picking up that the project has junit4 on the class path (?) and tries to load the junit-vintage-engine
.
The workaround in my case was to add testFixturesApi "org.junit.vintage:junit-vintage-engine:5.9.0"
to the Gradle config. It's a bit of an ugly hack, but posting this here in case it helps someone else.
Upstream IntelliJ issue: https://youtrack.jetbrains.com/issue/IDEA-233706/Failed-to-resolve-junit-vintage-engine-4.12.9-when-trying-to-run-JUnit-5-test#focus=Comments-27-8188989.0-0
Wish this could be resolved, testcontainers is the only part still pulling in Junit4 for us, it would be nice not having to tell junior developers anymore that half the test related annotations IntelliJ provides should not be used.
@void-spark If using Gradle, you can save your junior developers from themselves with
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute(module("junit:junit"))
.using(module("io.quarkus:quarkus-junit4-mock:3.0.0.Final"))
.because(
"We don't want JUnit 4; but is an unneeded transitive of testcontainers. " +
"See https://github.com/testcontainers/testcontainers-java/issues/970"
)
}
}
Which will yield
+--- org.testcontainers:testcontainers -> 1.17.6
| +--- junit:junit:4.13.2 -> io.quarkus:quarkus-junit4-mock:3.0.0.Final
| +--- \\ other dependencies
Since the "mock" doesn't contain all the common annotations/classes like @Test
, @Before
etc and only the handful of classes directly referred to by testcontainers, the completions are unlikely to be a problem.
And if you're worried about what's in it, can check out https://github.com/quarkusio/quarkus/tree/main/core/junit4-mock
Ugh. That's such an ugly hack :)
It's better to use Checkstyle, maven enforcer or ArchUnit for such things.
See https://stackoverflow.com/questions/61629824/preventing-the-use-of-junit4-libraries-in-a-project for some good answers
Ugh. That's such an ugly hack :)
It's better to use Checkstyle, maven enforcer or ArchUnit for such things.
In one way yes, but the nice part about the hack is that you don't even get @Test
, @Before
etc (as mentioned above) on your tests' classpath => editors like IntelliJ won't even attempt to suggest it to the user. In that way, it's more of a zeroconf approach, which is kind of nice.
I excluded JUnit 4 by adding the following to build.gradle
configurations {
testCompile {
exclude group: 'junit', module: 'junit'
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
testRuntime {
exclude group: 'junit', module: 'junit'
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
That may compile but doesnβt actually work.
Nope, still no 2.0, any timelines yet? :)
It's April 2024. It's time for 2.0 to fix this issue.This was opened in 2018, 6 years ago. Do you remember those days? No AI back then. No python. (oh wait, there was Python)
We also encountered this problem in our projects.
We couldn't find any junit4-mock dependency specifically for Testcontainers (besides the mock for quarkus mentioned above) so we simply wrote our own.
Feel free to use it :)
This is one of the things that always will be with us I think, I can not image how many times I bumped into something "junit4 vs junit5" - go solve your dependencies. It's been 7 years since Junit5 was released but the ghost will be us for a long time.
Let's get rid from 4, legacy will be legacy
I have to admit that I find it very surprising that this has not been addressed since Nov 2018 in a project with the impact, reach, success and motivation like Testcontainers.
Seems the only working solution for projects working with Testcontainers and disallowing Junit4 to guarantee that developers won't use junit4 in their tests is to use IllegalImport check of CheckStyle (https://checkstyle.org/checks/imports/illegalimport.html) and ban both junit4 specific packages:
- junit.*
- org.junit.matchers.*
- org.junit.rules.*
- org.junit.runner.*
- org.junit.runners.*
- org.junit.validator.*
and separately specific classes:
- org.junit.After
- org.junit.AfterClass
- org.junit.Assert
- org.junit.Before
- org.junit.BeforeClass
- org.junit.Rule
- org.junit.Test
In my case I opted by excluding all JUnit 4 dependencies and copy some of those required interfaces in the test sources.
Definitely I don't love it, but it seemed to me this was the best approach to ensure we only work with JUnit 5.
Seems the only working solution for projects working with Testcontainers and disallowing Junit4 to guarantee that developers won't use junit4 in their tests is to use IllegalImport check of CheckStyle (https://checkstyle.org/checks/imports/illegalimport.html) and ban both junit4 specific packages:
- junit.*
- org.junit.matchers.*
- org.junit.rules.*
- org.junit.runner.*
- org.junit.runners.*
- org.junit.validator.*
and separately specific classes:
- org.junit.After
- org.junit.AfterClass
- org.junit.Assert
- org.junit.Before
- org.junit.BeforeClass
- org.junit.Rule
- org.junit.Test