测试 GraalVM Native Image

在编写 native image 应用时,我们建议你尽可能继续使用 JVM 来开发大部分单元测试和集成测试。 这将有助于降低开发者的构建时间,并允许你使用现有的 IDE 集成。 通过在 JVM 上进行广泛的测试覆盖,你可以将 native image 测试重点放在可能不同的领域。

对于 native image 测试,你通常需要确保以下方面正常工作:

  • Spring AOT 引擎能够处理你的应用,并且它将在 AOT 处理模式下运行。

  • GraalVM 有足够的提示来确保可以生成有效的 native image。

使用 JVM 测试 Ahead-of-Time 处理

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

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

由于 native-image 编译阶段可能需要一些时间才能完成,有时在 JVM 上运行应用但使用 AOT 生成的初始化代码会很有用。 这样做可以帮助你快速验证 AOT 生成的代码中没有错误,并且当你的应用最终转换为 native image 时不会缺少任何内容。

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

例如:

$ java -Dspring.aot.enabled=true -jar myapplication.jar

注意:你需要确保你正在测试的 jar 包含 AOT 生成的代码。 对于 Maven,这意味着你应该使用 -Pnative 构建以激活 native profile。 对于 Gradle,你需要确保你的构建包含 org.graalvm.buildtools.native 插件。

如果你的应用在设置 spring.aot.enabled 属性为 true 的情况下启动,那么你就有更高的信心相信它在转换为 native image 时也能正常工作。

你还可以考虑对运行中的应用运行集成测试。 例如,你可以使用 Spring WebClient 来调用你的应用 REST 端点。 或者你可以考虑使用像 Selenium 这样的项目来检查你的应用的 HTML 响应。

使用 Native Build Tools 进行测试

GraalVM Native Build Tools 包括在 native image 中运行测试的功能。 当你想要深入测试应用内部在 GraalVM native image 中的工作时,这可能会很有帮助。

生成包含要运行的测试的 native image 可能是一个耗时的操作,因此大多数开发者可能更喜欢在本地使用 JVM。 但是,它们作为 CI 管道的一部分可能非常有用。 例如,你可以选择每天运行一次 native 测试。

Spring Framework 包括对运行测试的 ahead-of-time 支持。 所有常用的 Spring 测试功能都可以与 native image 测试一起使用。 例如,你可以继续使用 @SpringBootTest 注解。 你还可以使用 Spring Boot test slices 来仅测试应用的特定部分。

Spring Framework 的 native 测试支持按以下方式工作:

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

  • 对每个应用上下文应用 ahead-of-time 处理并生成资源。

  • 创建 native image,生成的资源由 GraalVM 处理。

  • native image 还包括配置了已发现测试列表的 JUnit TestEngine

  • 启动 native image,触发引擎,引擎将运行每个测试并报告结果。

使用 Maven

要使用 Maven 运行 native 测试,确保你的 pom.xml 文件使用 spring-boot-starter-parent。 你应该有一个看起来像这样的 <parent> 部分:

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

spring-boot-starter-parent 声明了一个 nativeTest profile,它配置了运行 native 测试所需的执行。 你可以使用命令行上的 -P 标志来激活 profiles。

提示:如果你不想使用 spring-boot-starter-parent,你需要为 Spring Boot 插件的 process-test-aot 目标和 Native Build Tools 插件的 test 目标配置执行。

要构建镜像并运行测试,使用激活 nativeTest profile 的 test 目标:

$ mvn -PnativeTest test

使用 Gradle

当应用 GraalVM Native Image 插件时,Spring Boot Gradle 插件会自动配置 AOT 测试任务。 你应该检查你的 Gradle 构建是否包含包含 org.graalvm.buildtools.nativeplugins 块。

要使用 Gradle 运行 native 测试,你可以使用 nativeTest 任务:

$ gradle nativeTest