测试 GraalVM 原生镜像

在编写原生镜像应用程序时,我们建议您尽可能继续使用 JVM 来开发大部分单元和集成测试。这将有助于缩短开发构建时间,并允许您使用现有的 IDE 集成。通过在 JVM 上进行广泛的测试覆盖,您可以将原生镜像测试重点放在可能存在差异的区域。

对于原生镜像测试,您通常需要确保以下方面有效:

  • Spring AOT 引擎能够处理您的应用程序,并且它将以 AOT 处理模式运行。

  • GraalVM 有足够的提示以确保可以生成有效的原生镜像。

使用 JVM 测试提前 (Ahead-of-Time) 编译

当 Spring Boot 应用程序运行时,它会尝试检测它是否作为原生镜像运行。如果它作为原生镜像运行,它将使用在构建时由 Spring AOT 引擎生成的代码来初始化应用程序。

如果应用程序运行在常规 JVM 上,则会忽略任何 AOT 生成的代码。

由于native-image编译阶段可能需要一段时间才能完成,因此有时在 JVM 上运行应用程序但让它使用 AOT 生成的初始化代码会很有用。这样做可以帮助您快速验证 AOT 生成的代码中没有任何错误,并且在应用程序最终转换为原生镜像时不会丢失任何内容。

要在 JVM 上运行 Spring Boot 应用程序并使其使用 AOT 生成的代码,可以将spring.aot.enabled系统属性设置为true

例如

$ java -Dspring.aot.enabled=true -jar myapplication.jar
您需要确保您正在测试的 jar 包含 AOT 生成的代码。对于 Maven,这意味着您应该使用-Pnative构建以激活native配置文件。对于 Gradle,您需要确保您的构建包含org.graalvm.buildtools.native插件。

如果您的应用程序在设置spring.aot.enabled属性为true的情况下启动,那么您可以更有信心它在转换为原生镜像时也能正常工作。

您还可以考虑对正在运行的应用程序运行集成测试。例如,您可以使用 Spring WebClient调用应用程序的 REST 端点。或者,您可以考虑使用 Selenium 等项目来检查应用程序的 HTML 响应。

使用原生构建工具进行测试

GraalVM 原生构建工具包括在原生镜像中运行测试的功能。当您想深入测试应用程序内部在 GraalVM 原生镜像中的工作情况时,这将非常有用。

生成包含要运行的测试的原生镜像是一个耗时的操作,因此大多数开发人员可能更倾向于在本地使用 JVM。但是,它们作为 CI 管道的一部分非常有用。例如,您可以选择每天运行一次原生测试。

Spring Framework 包含用于运行测试的提前(Ahead-of-time,AOT)支持。所有常用的 Spring 测试功能都适用于原生镜像测试。例如,您可以继续使用@SpringBootTest注解。您还可以使用 Spring Boot 测试切片来仅测试应用程序的特定部分。

Spring Framework 的原生测试支持的工作方式如下:

  • 分析测试以发现将需要的任何ApplicationContext实例。

  • 将提前处理应用于这些应用程序上下文,并生成资源。

  • 创建一个原生镜像,并由 GraalVM 处理生成的资源。

  • 原生镜像还包括配置了已发现测试列表的 JUnit TestEngine

  • 启动原生镜像,触发引擎,引擎将运行每个测试并报告结果。

使用 Maven

要使用 Maven 运行原生测试,请确保您的pom.xml文件使用spring-boot-starter-parent。您应该有一个类似这样的<parent>部分:

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>3.3.5</version>
</parent>

spring-boot-starter-parent声明一个nativeTest配置文件,该配置文件配置运行原生测试所需的执行。您可以使用命令行上的-P标志激活配置文件。

如果您不想使用spring-boot-starter-parent,则需要为 Spring Boot 插件的process-test-aot目标和原生构建工具插件的test目标配置执行。

要构建镜像并运行测试,请使用test目标并激活nativeTest配置文件:

$ mvn -PnativeTest test

使用 Gradle

当应用 GraalVM 原生镜像插件时,Spring Boot Gradle 插件会自动配置 AOT 测试任务。您应该检查您的 Gradle 构建是否包含一个包含org.graalvm.buildtools.nativeplugins块。

要使用 Gradle 运行原生测试,您可以使用nativeTest任务:

$ gradle nativeTest