简体   繁体   English

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

[英]Unable to integration-testing gradle multi-module Spring-Boot-Application

Within a Gradle multi-module project with the bootstrapping in its own module I'm unable to use MockMvc , because its need to reference the bootstrapping-module.在 Gradle 多模块项目中,在其自己的模块中进行引导,我无法使用MockMvc ,因为它需要引用引导模块。 I'm not sure if I have misconfigured something.我不确定我是否配置错误。 The basic structure is:基本结构是:

  • module: a module containing some REST-Services and needs a testImplementation-Dependency on starter模块:一个包含一些 REST-Services 的模块,需要一个 testImplementation-Dependency on starter
  • starter: the bootstrapping-module which gets the spring-boot-plugin applied and depends on module starter:应用了 spring-boot-plugin 并依赖于模块的引导模块

I have set up a minimal example ongithub using Spring-Boot 2.3.1.RELEASE and Gradle 6.4 with the following configuration:我使用 Spring-Boot 2.3.1.RELEASE 和 Gradle 6.4 在github上设置了一个最小示例,配置如下:

./settings.gradle.kts ./settings.gradle.kts

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

./build.gradle.kts ./build.gradle.kts

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

./starter/build.gradle.kts ./starter/build.gradle.kts

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

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

./module/build.gradle.kts ./module/build.gradle.kts

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

The starter -module contains only one a single class "Starter" referencing the module -module:启动器模块仅包含一个引用模块模块的 class “启动器”:

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

The module -module (*sigh I should have chosen a different name for this module) contains only this implemenation-class:模块-module(*sigh我应该为这个模块选择一个不同的名字)只包含这个实现类:

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

Additionally, the module -module has the following test-class doing the integration-test:此外, module -module 有以下测试类进行集成测试:

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());
    }
}

This code runs fine until the applying of the spring-boot-plugin within "./starter/build.gradle.kts".此代码运行良好,直到在“./starter/build.gradle.kts”中应用 spring-boot-plugin。 When the tasks "clean test" issued on the shell I get:当在 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

This problem does not occur, when tests are executed within the IDE (IntelliJ to be exact).在 IDE(确切地说是 IntelliJ)中执行测试时,不会出现此问题。

I already tried unsuccessfully to use the spring-dependency-management as suggested in this answer (as well as in several other answers).我已经尝试使用此答案(以及其他几个答案)中建议的 spring-dependency-management ,但未成功。

What have I done wrong?我做错了什么?

First off, I would recommend restructuring your project so you don't have cyclic dependencies.首先,我建议重组你的项目,这样你就没有循环依赖。 As it is now, in order to build starter , you need to build module .就像现在一样,为了构建starter ,您需要构建module And in order to test module , you need to build starter .为了测试module ,您需要构建starter Gradle can do it, but it is usually a smell. Gradle 可以,但一般是有气味的。

In terms of troubleshooting: when you get a test failure like this, look at the test report as that has the full stack trace.在故障排除方面:当您遇到这样的测试失败时,请查看测试报告,因为它具有完整的堆栈跟踪。 You should see that it complains that it can't find the Starter class ( Caused by: java.lang.ClassNotFoundException: de.kramhal.multi.Starter ), which is of cause in the starter module.您应该看到它抱怨找不到Starter class ( Caused by: java.lang.ClassNotFoundException: de.kramhal.multi.Starter ),这是在starter模块中的原因。

You mentioned the spring-dependency-management plugin, but that is only relevant for managing Maven dependencies, and not project dependencies like this.您提到了spring-dependency-management插件,但这仅与管理 Maven 依赖项相关,而不是像这样的项目依赖项。 So it is not helpful here.所以在这里没有帮助。

I am not entirely sure if this is Windows specific or not as I remember there were some discussions around performance a while back when having a lot of classes.我不完全确定这是否是 Windows 特定的,因为我记得前一段时间有很多课程时围绕性能进行了一些讨论。 But I believe the java-library plugin will look for jar files in other projects, and not the folder for compiled classes.但我相信java-library插件会在其他项目中查找 jar 文件,而不是编译类的文件夹。 This is a problem for you since the spring-boot plugin will by default disable the standard jar task and instead create "fat" a jar file through the bootJar task.这对您来说是个问题,因为spring-boot插件默认情况下会禁用标准jar任务,而是通过bootJar任务创建“胖” jar 文件。 Because you need both the fat jar for packaging the application to run stand-alone but also the normal jar for consuming it as a dependency, you need to do some tweaks to the starter project (Kotlin DSL):因为您既需要胖 jar 来打包应用程序以独立运行,还需要普通 jar 来将其用作依赖项,因此您需要对starter项目(Kotlin DSL)进行一些调整:

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

This will enable the normal jar file, but because the name will conflict with the one produced by the bootJar task, you need to rename one of them.这将启用正常的 jar 文件,但由于名称会与bootJar任务生成的名称冲突,因此您需要重命名其中一个。 I chose to rename the bootJar one.我选择将bootJar重命名为一个。

I don't know why the test works for you in IntelliJ as that should, by default, delegate everything to Gradle.我不知道为什么测试在 IntelliJ 中对您有效,因为默认情况下,应该将所有内容委托给 Gradle。 But maybe you have an old version, or done some manual configuration to let IntelliJ both compile and run your tests.但也许你有一个旧版本,或者做了一些手动配置让 IntelliJ 编译和运行你的测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM