此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Boot 3.3.4! |
此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Boot 3.3.4! |
Testcontainers 库提供了一种管理在 Docker 容器中运行的服务的方法。 它与 JUnit 集成,允许您编写一个测试类,该类可以在任何测试运行之前启动容器。 Testcontainers 对于编写与实际后端服务(如 MySQL、MongoDB、Cassandra 等)通信的集成测试特别有用。
Testcontainers 可以在 Spring Boot 测试中使用,如下所示:
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.boot.test.context.SpringBootTest;
@Testcontainers
@SpringBootTest
class MyIntegrationTests {
@Container
static Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:5");
@Test
void myTest() {
// ...
}
}
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection
@Testcontainers
@SpringBootTest
class MyIntegrationTests {
@Test
fun myTest() {
// ...
}
companion object {
@Container
@JvmStatic
val neo4j = Neo4jContainer("neo4j:5");
}
}
这将在运行任何测试之前启动运行 Neo4j(如果 Docker 在本地运行)的 docker 容器。 在大多数情况下,您需要配置应用程序以连接到容器中运行的服务。
服务连接
服务连接是与任何远程服务的连接。 Spring Boot 的自动配置可以使用服务连接的详细信息,并使用它们来建立与远程服务的连接。 执行此操作时,连接详细信息优先于任何与连接相关的配置属性。
使用 Testcontainers 时,可以通过在 test 类中注释 container 字段,为容器中运行的服务自动创建连接详细信息。
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
@Testcontainers
@SpringBootTest
class MyIntegrationTests {
@Container
@ServiceConnection
static Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:5");
@Test
void myTest() {
// ...
}
}
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
@Testcontainers
@SpringBootTest
class MyIntegrationTests {
@Test
fun myTest() {
// ...
}
companion object {
@Container
@ServiceConnection
@JvmStatic
val neo4j = Neo4jContainer("neo4j:5");
}
}
多亏了,上述配置允许应用程序中与 Neo4j 相关的 bean 与在 Testcontainers 管理的 Docker 容器中运行的 Neo4j 进行通信。
这是通过自动定义一个 bean 来完成的,然后由 Neo4j 自动配置使用,覆盖任何与连接相关的配置属性。@ServiceConnection
Neo4jConnectionDetails
您需要将模块添加为测试依赖项,以便将服务连接与 Testcontainers 一起使用。spring-boot-testcontainers |
服务连接注释由向 注册的类处理。
A 可以基于特定的子类或 Docker 镜像名称创建 Bean。ContainerConnectionDetailsFactory
spring.factories
ContainerConnectionDetailsFactory
ConnectionDetails
Container
jar 中提供了以下服务连接工厂:spring-boot-testcontainers
连接详细信息 | 匹配时间 |
---|---|
|
名为 “symptoma/activemq” 的容器或 |
|
类型的容器 |
|
类型的容器 |
|
类型的容器 |
|
类型的容器 |
|
类型的容器 |
|
类型的容器 |
|
类型为 的容器 ,或 |
|
类型的容器 |
|
类型的容器 |
|
类型的容器 |
|
名为 “otel/opentelemetry-collector-contrib” 或 |
|
名为 “otel/opentelemetry-collector-contrib” 或 |
|
名为 “otel/opentelemetry-collector-contrib” 或 |
|
类型的容器 |
|
类型为 、 、 、 或 |
|
类型的容器 |
|
或 类型的容器,或名为 “redis”、“redis/redis-stack” 或 “redis/redis-stack-server” 的容器 |
|
名为 “openzipkin/zipkin” 的容器 |
默认情况下,将为给定的 .
例如,a 将同时创建 和 。 如果只想创建适用类型的子集,则可以使用 的属性 . |
默认情况下,用于获取用于查找连接详细信息的名称。
Docker 镜像名称的存储库部分会忽略任何注册表和版本。
只要 Spring Boot 能够获取 instance 的实例,这就可以工作,例如上例中所示的字段。Container.getDockerImageName().getRepository()
Container
static
如果你正在使用方法, Spring Boot 不会调用 bean 方法来获取 Docker 镜像名称,因为这会导致急切的初始化问题。
相反,使用 bean 方法的返回类型来找出应该使用哪个连接详细信息。
只要您使用类型化容器(如 或 ),这就可以正常工作。
如果您使用的是 ,例如与 Redis 一起使用,这将停止工作,如以下示例所示:@Bean
Neo4jContainer
RabbitMQContainer
GenericContainer
-
Java
-
Kotlin
import org.testcontainers.containers.GenericContainer;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;
@TestConfiguration(proxyBeanMethods = false)
public class MyRedisConfiguration {
@Bean
@ServiceConnection(name = "redis")
public GenericContainer<?> redisContainer() {
return new GenericContainer<>("redis:7");
}
}
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.boot.testcontainers.service.connection.ServiceConnection
import org.springframework.context.annotation.Bean
import org.testcontainers.containers.GenericContainer
@TestConfiguration(proxyBeanMethods = false)
class MyRedisConfiguration {
@Bean
@ServiceConnection(name = "redis")
fun redisContainer(): GenericContainer<*> {
return GenericContainer("redis:7")
}
}
Spring Boot 无法判断使用了哪个容器镜像,因此必须使用属性from来提供该提示。GenericContainer
name
@ServiceConnection
您还可以使用 属性 of 来覆盖将使用的连接详细信息,例如在使用自定义图像时。
如果您使用的是 Docker 镜像 ,您将用于确保已创建。name
@ServiceConnection
registry.mycompany.com/mirror/myredis
@ServiceConnection(name="redis")
RedisConnectionDetails
您需要将模块添加为测试依赖项,以便将服务连接与 Testcontainers 一起使用。spring-boot-testcontainers |
连接详细信息 | 匹配时间 |
---|---|
|
名为 “symptoma/activemq” 的容器或 |
|
类型的容器 |
|
类型的容器 |
|
类型的容器 |
|
类型的容器 |
|
类型的容器 |
|
类型的容器 |
|
类型为 的容器 ,或 |
|
类型的容器 |
|
类型的容器 |
|
类型的容器 |
|
名为 “otel/opentelemetry-collector-contrib” 或 |
|
名为 “otel/opentelemetry-collector-contrib” 或 |
|
名为 “otel/opentelemetry-collector-contrib” 或 |
|
类型的容器 |
|
类型为 、 、 、 或 |
|
类型的容器 |
|
或 类型的容器,或名为 “redis”、“redis/redis-stack” 或 “redis/redis-stack-server” 的容器 |
|
名为 “openzipkin/zipkin” 的容器 |
默认情况下,将为给定的 .
例如,a 将同时创建 和 。 如果只想创建适用类型的子集,则可以使用 的属性 . |
动态属性
与服务连接相比,一个稍微详细但更灵活的替代方案是 。
static 方法允许向 Spring Environment 添加动态属性值。@DynamicPropertySource
@DynamicPropertySource
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
@Testcontainers
@SpringBootTest
class MyIntegrationTests {
@Container
static Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:5");
@Test
void myTest() {
// ...
}
@DynamicPropertySource
static void neo4jProperties(DynamicPropertyRegistry registry) {
registry.add("spring.neo4j.uri", neo4j::getBoltUrl);
}
}
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.DynamicPropertyRegistry
import org.springframework.test.context.DynamicPropertySource
import org.testcontainers.containers.Neo4jContainer
import org.testcontainers.junit.jupiter.Container
import org.testcontainers.junit.jupiter.Testcontainers
@Testcontainers
@SpringBootTest
class MyIntegrationTests {
@Test
fun myTest() {
// ...
}
companion object {
@Container
@JvmStatic
val neo4j = Neo4jContainer("neo4j:5");
@DynamicPropertySource
@JvmStatic
fun neo4jProperties(registry: DynamicPropertyRegistry) {
registry.add("spring.neo4j.uri") { neo4j.boltUrl }
}
}
}
上述配置允许应用程序中与 Neo4j 相关的 bean 与在 Testcontainers 管理的 Docker 容器内运行的 Neo4j 进行通信。