Testcontainers
Testcontainers 库提供了一种管理在 Docker 容器中运行的服务的方式。它与 JUnit 集成,允许您编写一个测试类,该测试类可以在任何测试运行之前启动一个容器。Testcontainers 特别适用于编写与真实后端服务(如 MySQL、MongoDB、Cassandra 等)通信的集成测试。
Testcontainers 可以像下面这样在 Spring Boot 测试中使用
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() {
// ...
}
}
这将在任何测试运行之前启动一个运行 Neo4j 的 Docker 容器(如果 Docker 在本地运行)。在大多数情况下,您需要配置应用程序以连接到容器中运行的服务。
服务连接
服务连接是与任何远程服务的连接。Spring Boot 的自动配置可以利用服务连接的详细信息,并使用它们来建立与远程服务的连接。这样做时,连接详细信息优先于任何与连接相关的配置属性。
使用 Testcontainers 时,可以通过在测试类中的容器字段上添加注释来自动为容器中运行的服务创建连接详细信息。
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() {
// ...
}
}
由于 @ServiceConnection
,上述配置允许应用程序中的 Neo4j 相关 bean 与 Testcontainers 管理的 Docker 容器中运行的 Neo4j 通信。这是通过自动定义一个 Neo4jConnectionDetails
bean 来完成的,该 bean 随后被 Neo4j 自动配置使用,覆盖任何与连接相关的配置属性。
您需要将 spring-boot-testcontainers 模块添加为测试依赖项,以便使用 Testcontainers 的服务连接。
|
服务连接注释由 ContainerConnectionDetailsFactory
类处理,这些类在 spring.factories
中注册。ContainerConnectionDetailsFactory
可以根据特定的 Container
子类或 Docker 镜像名称创建 ConnectionDetails
bean。
spring-boot-testcontainers
jar 中提供了以下服务连接工厂
连接详细信息 | 匹配 |
---|---|
|
名为 "symptoma/activemq" 的容器或 |
|
类型为 |
|
类型为 |
|
类型为 |
|
类型为 |
|
类型为 |
|
类型为 |
|
类型为 |
|
类型为 |
|
类型为 |
|
类型为 |
|
名为 "otel/opentelemetry-collector-contrib" 的容器 |
|
名为 "otel/opentelemetry-collector-contrib" 的容器 |
|
类型为 |
|
类型为 |
|
类型为 |
|
名为 "redis" 的容器 |
|
名为 "openzipkin/zipkin" 的容器 |
默认情况下,对于给定的 如果您只想创建部分适用的类型,可以使用 |
默认情况下,Container.getDockerImageName()
用于获取用于查找连接详细信息的名称。只要 Spring Boot 能够获取 Container
的实例,这就可以正常工作,例如在上面的示例中使用 static
字段时。
如果您使用的是 @Bean
方法,Spring Boot 不会调用 bean 方法来获取 Docker 镜像名称,因为这会导致急切初始化问题。相反,bean 方法的返回类型用于找出应使用哪个连接详细信息。只要您使用的是类型化容器,例如 Neo4jContainer
或 RabbitMQContainer
,这就可以正常工作。如果您使用的是 GenericContainer
,例如 Redis,则此方法将不再有效,如下面的示例所示
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");
}
}
Spring Boot 无法从 GenericContainer
中判断使用了哪个容器镜像,因此必须使用 @ServiceConnection
的 name
属性来提供该提示。
您还可以使用 @ServiceConnection
的 name
属性来覆盖将使用哪个连接详细信息,例如在使用自定义镜像时。如果您使用的是 Docker 镜像 registry.mycompany.com/mirror/myredis
,则可以使用 @ServiceConnection(name="redis")
来确保创建 RedisConnectionDetails
。
动态属性
与服务连接相比,@DynamicPropertySource
是一种稍微冗长但更灵活的替代方案。静态 @DynamicPropertySource
方法允许向 Spring 环境添加动态属性值。
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);
}
}
上述配置允许应用程序中的 Neo4j 相关 bean 与 Testcontainers 管理的 Docker 容器中运行的 Neo4j 进行通信。