Testcontainers Support

除了 using Testcontainers for integration testing 之外,在开发时也可以使用它们。下一节将提供有关此内容的更多详细信息。

As well as using Testcontainers for integration testing, it’s also possible to use them at development time. The next sections will provide more details about that.

Using Testcontainers at Development Time

这种方法允许开发人员快速启动应用程序依赖的服务的容器,从而无需手动配置数据库服务器等内容。以这种方式使用 Testcontainers 提供的功能与 Docker Compose 类似,只不过你的容器配置用 Java 编写,而不是 YAML。

This approach allows developers to quickly start containers for the services that the application depends on, removing the need to manually provision things like database servers. Using Testcontainers in this way provides functionality similar to Docker Compose, except that your container configuration is in Java rather than YAML.

要在开发时使用 Testcontainers,你需要使用 “test” 类路径而不是 “main” 来启动应用程序。这将允许你访问所有已声明的测试依赖关系,并为你提供一个编写测试配置的自然位置。

To use Testcontainers at development time you need to launch your application using your “test” classpath rather than “main”. This will allow you to access all declared test dependencies and give you a natural place to write your test configuration.

要创建应用程序的可测试启动版本,你应该在 src/test 目录中创建一个 “Application” 类。例如,如果你的主应用程序在 src/main/java/com/example/MyApplication.java,你应该创建 src/test/java/com/example/TestMyApplication.java

To create a test launchable version of your application you should create an “Application” class in the src/test directory. For example, if your main application is in src/main/java/com/example/MyApplication.java, you should create src/test/java/com/example/TestMyApplication.java

TestMyApplication 类可以使用 SpringApplication.from(…​) 方法启动真正的应用程序:

The TestMyApplication class can use the SpringApplication.from(…​) method to launch the real application:

你还需要定义要与应用程序一起启动的 Container 实例。为此,你需要确保将 spring-boot-testcontainers 模块已添加为 test 依赖关系。完成此操作后,你可以创建一个 @TestConfiguration 类,为要启动的容器声明 @Bean 方法。

You’ll also need to define the Container instances that you want to start along with your application. To do this, you need to make sure that the spring-boot-testcontainers module has been added as a test dependency. Once that has been done, you can create a @TestConfiguration class that declares @Bean methods for the containers you want to start.

你还可以使用 @ServiceConnection@Bean 方法添加注释,以创建 ConnectionDetails bean。有关受支持技术的详细信息,请参见 the service connections 部分。

You can also annotate your @Bean methods with @ServiceConnection in order to create ConnectionDetails beans. See the service connections section for details of the supported technologies.

典型的 Testcontainers 配置看上去如下:

A typical Testcontainers configuration would look like this:

Spring Boot 自动管理 Container bean 的生命周期。容器将自动启动和停止。

The lifecycle of Container beans is automatically managed by Spring Boot. Containers will be started and stopped automatically.

你可以使用 configprop:spring.testcontainers.beans.startup[] 属性来更改容器的启动方式。默认情况下,使用 sequential 启动,但如果希望并行启动多个容器,也可以选择 parallel

You can use the configprop:spring.testcontainers.beans.startup[] property to change how containers are started. By default sequential startup is used, but you may also choose parallel if you wish to start multiple containers in parallel.

定义了测试配置后,可以使用 with(…​) 方法将其附加到测试启动器:

Once you have defined your test configuration, you can use the with(…​) method to attach it to your test launcher:

现在,你可以像启动任何常规 Java main 方法应用程序一样,启动 TestMyApplication 以启动你的应用程序及运行应用程序所需的容器。

You can now launch TestMyApplication as you would any regular Java main method application to start your application and the containers that it needs to run.

你可以使用命令行上的 Maven goal spring-boot:test-run 或 Gradle 任务 bootTestRun 来执行此操作.

You can use the Maven goal spring-boot:test-run or the Gradle task bootTestRun to do this from the command line.

Contributing Dynamic Properties at Development Time

如果你想在开发期间从 Container @Bean 方法中提供动态属性,则可以通过注入 DynamicPropertyRegistry 来实现.此操作方式类似于你可以在测试中使用的 @DynamicPropertySource annotation.它允许你添加容器启动后即可使用的一些属性.

If you want to contribute dynamic properties at development time from your Container @Bean methods, you can do so by injecting a DynamicPropertyRegistry. This works in a similar way to the @DynamicPropertySource annotation that you can use in your tests. It allows you to add properties that will become available once your container has started.

典型的配置看起来如下所示:

A typical configuration would look like this:

建议在可能的情况下使用 @ServiceConnection,但是对于尚未拥有 @ServiceConnection 支持的技术,动态属性可以作为有用的备用选择.

Using a @ServiceConnection is recommended whenever possible, however, dynamic properties can be a useful fallback for technologies that don’t yet have @ServiceConnection support.

Importing Testcontainer Declaration Classes

使用 Testcontainers 时的一种常见模式是将 Container 实例声明为静态域.通常,这些域位于测试类中.它们也可以在一个父类中声明,或者在一个测试实现的接口中声明.

A common pattern when using Testcontainers is to declare Container instances as static fields. Often these fields are defined directly on the test class. They can also be declared on a parent class or on an interface that the test implements.

例如,以下 MyContainers 接口声明 mongoneo4j 容器:

For example, the following MyContainers interface declares mongo and neo4j containers:

如果你已经拥有此方式定义的容器或者你只是喜欢这种样式,那么你可以导入这些声明类,而不是将容器定义为 @Bean 方法.为此,请向你的测试配置类添加 @ImportTestcontainers 注释:

If you already have containers defined in this way, or you just prefer this style, you can import these declaration classes rather than defining you containers as @Bean methods. To do so, add the @ImportTestcontainers annotation to your test configuration class:

如果你不打算使用 service connections feature 但希望使用 @DynamicPropertySource,请从 Container 域中删除 @ServiceConnection 注释.你也可以向你的声明类中添加带 @DynamicPropertySource 注释的方法.

If you don’t intend to use the service connections feature but want to use @DynamicPropertySource instead, remove the @ServiceConnection annotation from the Container fields. You can also add @DynamicPropertySource annotated methods to your declaration class.

Using DevTools with Testcontainers at Development Time

当使用 devtools 时,你可以通过 @RestartScope 为 bean 和 bean 方法添加注释.当 devtools 重新启动应用程序时,这些 bean 将不会重新创建.这对 Testcontainer Container bean 特别有用,因为它们保留了在应用程序重新启动的情况下.

When using devtools, you can annotate beans and bean methods with @RestartScope. Such beans won’t be recreated when the devtools restart the application. This is especially useful for Testcontainer Container beans, as they keep their state despite the application restart.

如果你正在使用 Gradle 并希望使用此功能,则需要将 spring-boot-devtools 依赖项的配置从 developmentOnly 更改为 testAndDevelopmentOnly.在 developmentOnly 的默认范围内,bootTestRun 任务将不会拾取你的代码中的更改,因为 devtools 未处于活动状态.

If you’re using Gradle and want to use this feature, you need to change the configuration of the spring-boot-devtools dependency from developmentOnly to testAndDevelopmentOnly. With the default scope of developmentOnly, the bootTestRun task will not pick up changes in your code, as the devtools are not active.