Maven 使用 surefire-plugin 编译并为 JPMS 模块的单元测试提供范围

Maven compile and provided scopes for unit testing of JPMS module with surefire-plugin

试图测试我的 maven 项目(一个父 pom 和几个模块(jpms 模块))我很烦人 Error occurred in starting fork:

Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:3.0.0-M4:test (default-test) on project com.foo.plugin: There are test failures.
...
Error occurred in starting fork, check output in log
Process Exit Code: 1
org.apache.maven.surefire.booter.SurefireBooterForkException: The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
...
Error occurred in starting fork, check output in log
Process Exit Code: 1
    at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:690)
    at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:285)
    at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:248)
    at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1217)
    at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:1063)
    at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:889)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginM

我找到的解决方案,例如here suggested to set <forkCount>0</forkCount> in surefire-plugin configuration. However, such solution doesn't allow to run tests on module-path, so I went to this surefire issue

Surefire 开发人员(感谢他们)发现​​原因是在我使用的依赖项的 maven 范围内。在我的项目中我有:

         <dependency>
            <groupId>jakarta.ws.rs</groupId>
            <artifactId>jakarta.ws.rs-api</artifactId>
            <version>2.1.6</version>
            <scope>provided</scope> <!-- NOTE IT -->
        </dependency>
        <dependency>
            <groupId>jakarta.xml.bind</groupId>
            <artifactId>jakarta.xml.bind-api</artifactId>
            <version>2.3.2</version>
            <scope>provided</scope> <!-- NOTE IT -->
        </dependency>

他们说必须是:

          <dependency>
            <groupId>jakarta.ws.rs</groupId>
            <artifactId>jakarta.ws.rs-api</artifactId>
            <version>2.1.6</version>
            <scope>compile</scope> <!-- NOTE IT -->
        </dependency>
        <dependency>
            <groupId>jakarta.xml.bind</groupId>
            <artifactId>jakarta.xml.bind-api</artifactId>
            <version>2.3.2</version>
            <scope>compile</scope> <!-- NOTE IT -->
        </dependency>

当我更改范围时,我的项目通过 surefire 测试没有问题。 jakarta.ws.rs-apijakarta.xml.bind-api 这两个依赖项都是 JPMS 模块,并且是 required 我的 JPMS 模块。

所以问题是我的代码有问题(如果我想 运行 我的 JPMS 模块测试,provided 是错误的)还是 surefire 插件有问题?

注意:您可以随意删除 <scope>compile</scope>,因为在您的 POM 中没有范围声明意味着 Maven 将无论如何使用默认值 compile

提供的范围是项目架构方面。

它用于应用服务器包含 WS API(即使不同的工件文件名)的情况。这样我们将其标记为 provided,这使得 WAR 文件更小并且不会包含 WS API 工件。

在构建无服务器应用程序和构建自己的容器的情况下,不需要声明 provided 的范围。工件将出现在 Fat JAR 中,这正是您所期望的。

如您所见,标记为已提供的依赖项处理类路径。它出现在编译器类路径中,但未出现在运行时中。

范围 provided 中还有一项功能。它是继承,其中这种依赖不能被传递继承。 如果您在 POM 中提供的范围内有这样的依赖关系,那么继承将不会在依赖的子 POM 中看到依赖关系。

有关更多信息,请参阅 Maven 文档。

http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

This scope is only available on the compilation and test classpath, and is not transitive.