16

I'm reading Junit 5 User Guide. It leads me to a JUnit 5 Jupiter Gradle Sample, which is a simplest example of using Junit 5 with Gradle. In build.gradle file, there are 2 dependencies, junit-jupiter and junit-bom. And in test task, it also calls useJUnitPlatform() function.

plugins {
    id 'java'
}

repositories {
    mavenCentral()
}

dependencies {
    testImplementation(platform('org.junit:junit-bom:5.7.1'))
    testImplementation('org.junit.jupiter:junit-jupiter')
}

test {
    useJUnitPlatform()
    testLogging {
        events "passed", "skipped", "failed"
    }
}

According to my knowledge, the junit-jupiter is the aggregate artifact, which pulls the following 3 artifacts,

  1. junit-jupiter-api (compile dependency)
  2. junit-jupiter-engine (runtime dependency)
  3. junit-jupiter-params (for parameterized tests)

So I guess junit-jupiter is already enough for running JUnit Jupiter in my project (correct me if I was wrong). I want to know what is junit-bom and JUnitPlatform for here? Can I simply get rid of them? Thanks everyone:)

shen
  • 933
  • 10
  • 19

1 Answers1

18

The junit-bom is JUnit's Bill Of Materials (BOM). When including this BOM, it will ensure to align and manage all JUnit 5 dependency versions for you. You can find more information about the BOM concept as part of this article.

That's why you don't have to specify a version when importing junit-jupiter:

// with the BOM, no version needed
testImplementation('org.junit.jupiter:junit-jupiter')

// when using no BOM, version info is needed
testImplementation('org.junit.jupiter:junit-jupiter:5.7.1')

You'll see the benefit of the BOM in case you import multiple dependencies from the same project. When just using one dependency, it might seem redundant:

// only define the version at a central place, that's nice
testImplementation(platform('org.junit:junit-bom:5.7.1'))
testImplementation('org.junit.jupiter:junit-jupiter')
testImplementation('org.junit.vintage:junit-vintage-engine') // when you want to also run JUnit 3 + 4 tests

The useJUnitPlatform() instructs the Gradle test task to use the JUnit Platform for executing your tests. That's required.

In your case, you have a minimal working setup to use JUnit 5 for a Gradle project. What you could do is to remove the junit-bom and add the version information yourself:

plugins {
    id 'java'
}

repositories {
    mavenCentral()
}

dependencies {
    testImplementation('org.junit.jupiter:junit-jupiter:5.7.1')
}

test {
    useJUnitPlatform()
    testLogging {
        events "passed", "skipped", "failed"
    }
}

But I would stick to the recommendation of the JUnit team and their sample projects on GitHub.

rieckpil
  • 10,470
  • 3
  • 32
  • 56
  • Great explanation of `junit-bom`! And for `JUnitPlatform()`, can I treat it as a test `Runner`? So that I don't have to explicitly write a `TestRunner` class to run the test? – shen Apr 30 '21 at 05:42
  • with `JUnitPlatform()` you are referring to `useJUnitPlatform()`, right? By `Runner` you mean the JUnit 4 `Runner` API? Maybe the [relevant part](https://docs.gradle.org/current/userguide/java_testing.html#using_junit5) of the Gradle documentation can help here. – rieckpil Apr 30 '21 at 06:07
  • thanks for the references, I think I'm very close to the answer now. perhaps junit 5 just makes thing way too complicated than it should be... – shen Apr 30 '21 at 06:20
  • According to the documentation: https://junit.org/junit5/docs/current/user-guide/#running-tests-build-spring-boot: "...If your build relies on dependency management support from Spring Boot, you should not import the junit-bom in your build script since that will result in duplicate (and potentially conflicting) management of JUnit dependencies..." and therefore I wonder in general whether it is a good idea to use the BOM and whether Spring Boot is just a single case that causes problems ... – becke-ch Nov 11 '22 at 14:55