设置多版本 JAR 单元测试

jqn*_*qno 15 java maven

我有一个项目使用了大量反射,还涉及“新”Java 功能,例如记录和密封类。我正在写这样的课程:

public class RecordHelper {
    public static boolean isRecord(Class<?> type) {
        return type.isRecord();
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,这仅适用于 Java 16 及更高版本,因此我尝试设置一个多版本 JAR 文件,其默认实现如下:

public class RecordHelper {
    public static boolean isRecord(Class<?> type) {
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经能够使用Baeldung 上的这篇文章使用 Maven 进行设置,并且效果很好。这很好,因为它不依赖于不同版本的单独配置文件,这使我的 pom 文件保持干净。

但现在我需要编写测试。

我希望能够在我想要支持的所有平台上运行测试套件,这意味着 JDK 8 及更高版本的所有平台。(我不介意在运行测试之前在不同的 JDK 上进行编译。)当然,在 JDK 16 及更高版本上,我也想测试与记录相关的东西(以及在 17 及更高版本上,密封类),所以这意味着我必须编译一些记录,这意味着我将不可避免地拥有一些无法在较旧的 JDK 上运行的类文件。

在我看来,拥有一个用于测试的多版本 JAR 文件也是有意义的,其中记录测试被放置在 中的适当位置META-INF/versions,但当然测试通常不会打包在 JAR 中,因此不起作用。

有没有办法让它在单模块 Maven 项目中工作而不需要太多重复?

当然,随着 JDK 版本的上升,它必须“积累”测试类,例如,在 JDK 8 上,我只有“常规”测试类,在 JDK 16 上,我有常规测试类和那些测试类,在java16JDK 17 上,我只有“常规”测试类。有常规的、java16那些的和java17那些的。我还没有找到一种方法可以在 Maven 中以简洁的方式表达这种事情,但我不是 Maven 专家。

或者我看错了方向,最好是创建一个多模块 Maven 项目,将主代码放在一个模块中,将测试放在另一个模块中,然后也为测试生成一个多模块 jar ?如果是这样,我如何在不同的 JDK 上运行这个 jar 文件?

jqn*_*qno 1

我最终创建了一个多模块构建,正如@khmarbaise 在问题下面的评论之一中所建议的那样。他还举了一个例子

对于名为corem16m17等的模块,我可以将大部分测试放在core模块中,并将 JDK 特定测试放在相应的模块中。我什至可以测试 JDK 特定代码与模块其余部分的集成core,因为显然在这个设置中,Maven 在 中选择了一个类的实现,而m17不是在 中同一类的实现core,从而模拟了真实的多实例中发生的情况。 -释放jar文件。我不能 100% 确定这是否是巧合,但它确实有效

多模块方法的另一个优点是,如果我在 JDK 特定的子模块中使用新的语言功能,我的 IDE 就会理解它。使用我在问题中引用的 Baeldung 文章中的方法,这是行不通的,而且我到处都看到曲线。

为了测试不同 JDK 上的构建,我使用在 JDK 版本上激活的配置文件,并选择适当的子模块,如下所示:

        <profile>
            <id>modules-jdk8</id>
            <activation>
                <jdk>[1.8,11)</jdk>
            </activation>
            <modules>
                <module>core</module>
            </modules>
        </profile>

        <profile>
            <id>modules-jdk16</id>
            <activation>
                <jdk>[16,17)</jdk>
            </activation>
            <modules>
                <module>core</module>
                <module>m16</module>
            </modules>
        </profile>

        <profile>
            <id>modules-jdk17</id>
            <activation>
                <jdk>[17,)</jdk>
            </activation>
            <modules>
                <module>core</module>
                <module>m16</module>
                <module>m17</module>
                <module>release</module>
            </modules>
        </profile>
Run Code Online (Sandbox Code Playgroud)

(也许使用工具链的方法会更好。)

请注意,还必须有一个release模块,该模块依赖于所有其他模块,并且使用 Maven Assembly 插件实际创建 jar 文件,并将 JDK 特定的类放置在 jar 中的适当目录中。

我已经<maven.install>true</maven.install>向除该release模块之外的所有模块添加了一个属性,以便只有实际的多版本 jar 文件才会安装到我的本地存储库中。这很重要,因为我也想发布到 Maven Central,并且我不想将各种半成品 jar 文件扔在其中。