使用 JUnit 5 的 spring-boot-starter-test

Posted

技术标签:

【中文标题】使用 JUnit 5 的 spring-boot-starter-test【英文标题】:spring-boot-starter-test with JUnit 5 【发布时间】:2019-03-22 13:46:28 【问题描述】:

从 2.0.6 开始使用 spring-boot-starter-test 会引入 JUnit 4 依赖项。如何使用 spring-boot-starter-test(通过 Gradle),但使用 JUnit 5,而不引入 JUnit 4 依赖项?

如果有帮助,这里是 Gradle 的依赖输出的一部分:

+--- org.springframework.boot:spring-boot-starter-test -> 2.0.5.RELEASE
|    +--- org.springframework.boot:spring-boot-starter:2.0.5.RELEASE (*)
|    +--- org.springframework.boot:spring-boot-test:2.0.5.RELEASE
|    |    \--- org.springframework.boot:spring-boot:2.0.5.RELEASE (*)
|    +--- org.springframework.boot:spring-boot-test-autoconfigure:2.0.5.RELEASE
|    |    +--- org.springframework.boot:spring-boot-test:2.0.5.RELEASE (*)
|    |    \--- org.springframework.boot:spring-boot-autoconfigure:2.0.5.RELEASE (*)
|    +--- com.jayway.jsonpath:json-path:2.4.0
|    |    +--- net.minidev:json-smart:2.3
|    |    |    \--- net.minidev:accessors-smart:1.2
|    |    |         \--- org.ow2.asm:asm:5.0.4
|    |    \--- org.slf4j:slf4j-api:1.7.25
|    +--- junit:junit:4.12
|    |    \--- org.hamcrest:hamcrest-core:1.3

这是我的 build.gradle 文件:

buildscript 
    ext 
        springBootVersion = '2.0.6.RELEASE'
    rootGradleDir = "$rootProject.rootDir/gradle"
    
    repositories 
        mavenCentral()
    
    dependencies 
        classpath("org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion")
    


apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

apply from: "$rootGradleDir/staticCodeAnalysis.gradle"

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories 
    mavenCentral()


test 
  useJUnitPlatform()


dependencies 
    implementation('org.springframework.boot:spring-boot-starter-data-jpa')
    implementation('org.springframework.boot:spring-boot-starter-jdbc')
    implementation('org.springframework.boot:spring-boot-starter-security')
    implementation('org.springframework.boot:spring-boot-starter-thymeleaf')
    implementation('org.springframework.boot:spring-boot-starter-validation')
    implementation('org.springframework.boot:spring-boot-starter-web')
    implementation('org.liquibase:liquibase-core')
    runtimeOnly('org.springframework.boot:spring-boot-devtools')
  runtimeOnly('org.postgresql:postgresql')
  testImplementation('org.springframework.boot:spring-boot-starter-test')
  testImplementation('org.springframework.security:spring-security-test')

  implementation('org.glassfish.jaxb:jaxb-runtime:2.3.1')
  implementation('org.glassfish.jaxb:jaxb-runtime2.3.1')
  implementation('org.springframework.boot:spring-boot-starter-data-redis')

  testCompile('org.junit.jupiter:junit-jupiter-api:5.3.1')
  testCompile('org.junit.jupiter:junit-jupiter-params:5.3.1')
  testRuntime('org.junit.jupiter:junit-jupiter-engine:5.3.1')


更新

添加 JUnit 5 依赖项并执行 cmets 中提到的排除操作就成功了。测试依赖现在看起来像这样:

testImplementation('org.springframework.boot:spring-boot-starter-test') 
    exclude group: 'junit', module: 'junit' //by both name and group

【问题讨论】:

检查这个dzone.com/articles/…。你只需要排除junit 4 @lealceldeiro 刚刚试了一下,确实有效。谢谢! 【参考方案1】:

对其他贡献者提到的一些补充说明:

使用 Spring Boot > 2.4.0

如果您正在使用 Spring Boot > 2.4.0,那么您无需执行任何操作即可使用 JUnit 5 Jupiter,因为 spring-boot-starter-test 库不再包含 Vintage-engine 依赖项(可传递地包含 JUnit 4),只需将启动器依赖项包含到项目中就可以了。在 Gradle 配置中使用 useJUnitPlatform()

使用 2.4.0 > Spring Boot > 2.2.0

如果您使用早期版本,我建议使用高于 2.2.0.RELEASE 的版本,这是 Spring 团队默认将 JUnit 5 Jupiter 支持添加到 spring-boot-starter-test 的地方。

在这些版本中,该库还包含 Vintage Engine 依赖项,可用于使用 JUnit 5 Jupiter 平台运行 JUnit 4 测试。如果您不需要执行 JUnit 4 测试,那么 Spring 团队建议排除 org.junit.vintage:junit-vintage-engine(不仅仅是描述中指出的 junit):

testCompile('org.springframework.boot:spring-boot-starter-test') 
    exclude group: 'org.junit.vintage'

当然,您还需要在这里配置useJUnitPlatform() 指令。

【讨论】:

【参考方案2】:

这里使用实现而不是编译

test 
  useJUnitPlatform()


dependencies 
    testImplementation('org.springframework.boot:spring-boot-starter-test') 
        exclude group: 'junit', module: 'junit'
    
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.2'
    testImplementation 'org.junit.jupiter:junit-jupiter-params:5.4.2'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.2'

2020 年 10 月 29 日更新

在我们的 Spring Boot 2.3 项目中,我们不再需要这个 sn-p。默认情况下它已经在使用 JUnit 5。

【讨论】:

【参考方案3】:

只需添加

testImplementation('org.springframework.boot:spring-boot-starter-test') 
    exclude group: 'junit', module: 'junit'

testImplementation 'org.junit.jupiter:junit-jupiter:5.4.2'

还有:

test 
    useJUnitPlatform()

【讨论】:

【参考方案4】:

似乎较新版本的 spring-boot-starter-test(在 2.2.6/2.2.7 中注意到)正在导入 org.junit.vintage:junit-vintage-engine,它对 junit:junit 具有传递依赖。 仅排除 junit 给了我一些虚假错误:

May 13, 2020 9:20:05 AM org.junit.platform.launcher.core.DefaultLauncher handleThrowable
WARNING: TestEngine with ID 'junit-vintage' failed to discover tests
java.lang.NoClassDefFoundError: junit/runner/Version
...
Caused by: java.lang.ClassNotFoundException: junit.runner.Version
...

设置:

testCompile('org.springframework.boot:spring-boot-starter-test') 
    exclude group: 'org.junit.vintage'

为我成功了,所有测试都继续正常运行

【讨论】:

【参考方案5】:

十个月后,使用Gradle 5.4.1Spring Boot 2.1.7.RELEASEJUnit 5.5.1,我发现我使用的依赖项与其他答案不同。此外,我发现最好包含聚合工件而不是单个工件:

testImplementation('org.junit.jupiter:junit-jupiter:5.5.1')

您可以从我的另一个 SO Q&A 中了解更多关于我的观察:Interaction between Spring Boot and JUnit 5 — must use the overall artifacts not the individuals?

【讨论】:

【参考方案6】:

从 Gradle 4.6 开始(我相信),有原生的 JUnit 5 支持。您可以按如下方式包含 JUnit5:

dependencies 
  testCompile "org.junit.jupiter:junit-jupiter-api:5.2.0"
  testCompile "org.junit.jupiter:junit-jupiter-params:5.2.0"
  testRuntime "org.junit.jupiter:junit-jupiter-engine:5.2.0"

您还需要:

test 
  useJUnitPlatform()

JUnit 4 和 5 使用不同的包名,因此它们可以共存于同一个项目中。许多注释都是相同的(@Test 等),因此请确保将它们包含在 org.junit.jupiter.api 包中。

【讨论】:

谢谢。我也这样做了,但 JUnit 4 依赖项仍然存在。听起来@lealceldeiro 提到的排除路由是这里的方法。 正确,如果您根本不想包含它,则需要排除它。

以上是关于使用 JUnit 5 的 spring-boot-starter-test的主要内容,如果未能解决你的问题,请参考以下文章

如何使用junit在spring-boot中测试常见错误ErrorController

如何 JUnit 测试 Spring-Boot 的 Application.java

如何在spring-boot应用程序的junit中调用ApplicationContextInitializer

Maven 依赖于 Spring Boot 和 Junit

Spring-boot官方案例分析之data-jpa

使用 spring-data-jpa 和 MockMvc 进行 spring boot junit 测试