无法集成测试 gradle 多模块 Spring-Boot-Application

Unable to integration-testing gradle multi-module Spring-Boot-Application

在一个 Gradle 多模块项目中,在其自己的模块中进行引导,我无法使用 MockMvc,因为它需要引用引导模块。我不确定我是否配置错误。基本结构为:

我使用 Spring-Boot 2.3.1.RELEASE 和 Gradle 6.4 在 github 上设置了一个最小示例,配置如下:

./settings.gradle.kts

rootProject.name = "spring-multimodule-integrationtest"
include("starter", "module")

./build.gradle.kts

subprojects {
    repositories {
        jcenter()
    }
    dependencies {
        apply(plugin = "java-library")
        "testImplementation"("junit:junit:4.12")
    }
}

./starter/build.gradle.kts

plugins {
    id("org.springframework.boot") version "2.3.1.RELEASE"
}

dependencies {
    implementation(project(":module"))
}

./module/build.gradle.kts

dependencies {
    testImplementation(project(":starter"))
}

starter-模块仅包含一个 class"Starter" 引用 模块-模块:

public class Starter {
    public String info() { return "starter"; }
    public static void main(String[] args) {
        System.out.println(new Starter().info() + " and " + new Module().info());
    }
}

模块-模块(*唉我应该为这个模块选择一个不同的名字)只包含这个实现-class:

public class Module {
    public String info() { return "module"; }
}

此外,模块-模块有以下测试-class进行集成测试:

public class IntegrationTest
{
    @Test public void testSomeLibraryMethod() {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        System.setOut(new PrintStream(out));
        Starter.main(new String[0]);
        assertEquals("starter and module\n", out.toString());
    }
}

此代码运行良好,直到在“./starter/build.gradle.kts”中应用 spring-boot-plugin。当任务 "clean test" 在 shell 上发布时,我得到:

❯ ./gradlew clean test

> Task :module:test FAILED

de.kramhal.multi.IntegrationTest > testSomeLibraryMethod FAILED
    java.lang.NoClassDefFoundError at IntegrationTest.java:17
        Caused by: java.lang.ClassNotFoundException at IntegrationTest.java:17

1 test completed, 1 failed

当在 IDE(确切地说是 IntelliJ)中执行测试时,不会出现此问题。

我已经尝试按照 answer(以及其他几个答案)中的建议使用 spring-dependency-management,但没有成功。

我做错了什么?

首先,我会建议重组您的项目,这样您就没有循环依赖。就像现在一样,为了构建 starter,您需要构建 module。为了测试 module,您需要构建 starter。 Gradle可以做到,但一般都是闻到味道。

在故障排除方面:当您遇到这样的测试失败时,请查看具有完整堆栈跟踪的测试报告。您应该看到它抱怨找不到 Starter class (Caused by: java.lang.ClassNotFoundException: de.kramhal.multi.Starter),这是 starter 模块中的原因。

您提到了 spring-dependency-management 插件,但这只与管理 Maven 依赖项相关,而不是像这样的项目依赖项。所以在这里没有帮助。

我不完全确定这是否是 Windows 具体的,因为我记得不久前有一些关于性能的讨论,当时有很多 classes。但我相信 java-library 插件会在其他项目中寻找 jar 文件,而不是编译后的文件夹 classes。这对您来说是个问题,因为 spring-boot 插件默认会禁用标准 jar 任务,而是通过 bootJar 任务创建 "fat" 一个 jar 文件。因为您既需要用于将应用程序打包到 运行 独立应用程序的 fat jar,也需要用于将其作为依赖项使用的普通 jar,因此您需要对 starter 项目 (Kotlin DSL) 进行一些调整:

tasks {
    jar {
        enabled = true
    }
    bootJar {
        archiveClassifier.set("boot")
    }
}

这将启用普通的jar 文件,但由于名称会与bootJar 任务生成的名称冲突,您需要重命名其中一个。我选择重命名 bootJar 一个。

我不知道为什么测试在 IntelliJ 中对你有效,因为默认情况下应该将所有内容委托给 Gradle。但是也许你有一个旧版本,或者做了一些手动配置让 IntelliJ 编译和 运行 你的测试。