Testcontainers 库提供了一种管理在 Docker 容器中运行的服务的方法。 它与 JUnit 集成,允许您编写一个测试类,该类可以在任何测试运行之前启动容器。 Testcontainers 对于编写与真正的后端服务(如 MySQL、MongoDB、Cassandra 等)通信的集成测试特别有用。Spring中文文档

Testcontainers 可以在 Spring Boot 测试中使用,如下所示: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;

@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中文文档

服务连接

服务连接是与任何远程服务的连接。 Spring Boot 的自动配置可以使用服务连接的详细信息,并使用它们来建立与远程服务的连接。 执行此操作时,连接详细信息优先于任何与连接相关的配置属性。Spring中文文档

使用 Testcontainers 时,可以通过批注测试类中的容器字段,为容器中运行的服务自动创建连接详细信息。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.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 自动配置使用它,覆盖任何与连接相关的配置属性。@ServiceConnectionNeo4jConnectionDetailsSpring中文文档

需要将模块添加为测试依赖项,以便将服务连接与 Testcontainers 配合使用。spring-boot-testcontainers

服务连接注释由注册到 的类处理。 A 可以基于特定的子类或 Docker 映像名称创建 Bean。ContainerConnectionDetailsFactoryspring.factoriesContainerConnectionDetailsFactoryConnectionDetailsContainerSpring中文文档

jar 中提供了以下服务连接工厂:spring-boot-testcontainersSpring中文文档

连接详细信息 匹配于

ActiveMQConnectionDetailsSpring中文文档

名为“symptoma/activemq”或ActiveMQContainerSpring中文文档

ArtemisConnectionDetailsSpring中文文档

容器类型ArtemisContainerSpring中文文档

CassandraConnectionDetailsSpring中文文档

容器类型CassandraContainerSpring中文文档

CouchbaseConnectionDetailsSpring中文文档

容器类型CouchbaseContainerSpring中文文档

ElasticsearchConnectionDetailsSpring中文文档

容器类型ElasticsearchContainerSpring中文文档

FlywayConnectionDetailsSpring中文文档

容器类型JdbcDatabaseContainerSpring中文文档

JdbcConnectionDetailsSpring中文文档

容器类型JdbcDatabaseContainerSpring中文文档

KafkaConnectionDetailsSpring中文文档

容器类型或org.testcontainers.containers.KafkaContainerRedpandaContainerSpring中文文档

LiquibaseConnectionDetailsSpring中文文档

容器类型JdbcDatabaseContainerSpring中文文档

MongoConnectionDetailsSpring中文文档

容器类型MongoDBContainerSpring中文文档

Neo4jConnectionDetailsSpring中文文档

容器类型Neo4jContainerSpring中文文档

OtlpMetricsConnectionDetailsSpring中文文档

名为“otel/opentelemetry-collector-contrib”的容器Spring中文文档

OtlpTracingConnectionDetailsSpring中文文档

名为“otel/opentelemetry-collector-contrib”的容器Spring中文文档

PulsarConnectionDetailsSpring中文文档

容器类型PulsarContainerSpring中文文档

R2dbcConnectionDetailsSpring中文文档

类型为 、 、 、 或 的容器MariaDBContainerMSSQLServerContainerMySQLContainerOracleContainerPostgreSQLContainerSpring中文文档

RabbitConnectionDetailsSpring中文文档

容器类型RabbitMQContainerSpring中文文档

RedisConnectionDetailsSpring中文文档

名为“redis”的容器Spring中文文档

ZipkinConnectionDetailsSpring中文文档

名为“openzipkin/zipkin”的容器Spring中文文档

缺省情况下,将为给定的 . 例如,a 将同时创建 和 。ContainerPostgreSQLContainerJdbcConnectionDetailsR2dbcConnectionDetailsSpring中文文档

如果只想创建适用类型的子集,则可以使用 的属性。type@ServiceConnectionSpring中文文档

默认情况下,用于获取用于查找连接详细信息的名称。 Docker 映像名称的存储库部分忽略任何注册表和版本。 只要 Spring Boot 能够获取 的实例,这就有效,这在使用如上例所示的字段时就是这种情况。Container.getDockerImageName().getRepository()ContainerstaticSpring中文文档

如果您使用的是某个方法,Spring Boot 不会调用 bean 方法来获取 Docker 映像名称,因为这会导致急切的初始化问题。 相反,Bean 方法的返回类型用于找出应使用哪个连接详细信息。 只要您使用类型化容器,这就有效,例如 或。 如果您使用 ,例如与 Redis 一起使用,这将停止工作,如以下示例所示:@BeanNeo4jContainerRabbitMQContainerGenericContainerSpring中文文档

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 属性来提供该提示。GenericContainername@ServiceConnectionSpring中文文档

您还可以使用 of 属性来覆盖将使用的连接详细信息,例如在使用自定义映像时。 如果您使用的是 Docker 映像,则用于确保已创建。name@ServiceConnectionregistry.mycompany.com/mirror/myredis@ServiceConnection(name="redis")RedisConnectionDetailsSpring中文文档

需要将模块添加为测试依赖项,以便将服务连接与 Testcontainers 配合使用。spring-boot-testcontainers
连接详细信息 匹配于

ActiveMQConnectionDetailsSpring中文文档

名为“symptoma/activemq”或ActiveMQContainerSpring中文文档

ArtemisConnectionDetailsSpring中文文档

容器类型ArtemisContainerSpring中文文档

CassandraConnectionDetailsSpring中文文档

容器类型CassandraContainerSpring中文文档

CouchbaseConnectionDetailsSpring中文文档

容器类型CouchbaseContainerSpring中文文档

ElasticsearchConnectionDetailsSpring中文文档

容器类型ElasticsearchContainerSpring中文文档

FlywayConnectionDetailsSpring中文文档

容器类型JdbcDatabaseContainerSpring中文文档

JdbcConnectionDetailsSpring中文文档

容器类型JdbcDatabaseContainerSpring中文文档

KafkaConnectionDetailsSpring中文文档

容器类型或org.testcontainers.containers.KafkaContainerRedpandaContainerSpring中文文档

LiquibaseConnectionDetailsSpring中文文档

容器类型JdbcDatabaseContainerSpring中文文档

MongoConnectionDetailsSpring中文文档

容器类型MongoDBContainerSpring中文文档

Neo4jConnectionDetailsSpring中文文档

容器类型Neo4jContainerSpring中文文档

OtlpMetricsConnectionDetailsSpring中文文档

名为“otel/opentelemetry-collector-contrib”的容器Spring中文文档

OtlpTracingConnectionDetailsSpring中文文档

名为“otel/opentelemetry-collector-contrib”的容器Spring中文文档

PulsarConnectionDetailsSpring中文文档

容器类型PulsarContainerSpring中文文档

R2dbcConnectionDetailsSpring中文文档

类型为 、 、 、 或 的容器MariaDBContainerMSSQLServerContainerMySQLContainerOracleContainerPostgreSQLContainerSpring中文文档

RabbitConnectionDetailsSpring中文文档

容器类型RabbitMQContainerSpring中文文档

RedisConnectionDetailsSpring中文文档

名为“redis”的容器Spring中文文档

ZipkinConnectionDetailsSpring中文文档

名为“openzipkin/zipkin”的容器Spring中文文档

缺省情况下,将为给定的 . 例如,a 将同时创建 和 。ContainerPostgreSQLContainerJdbcConnectionDetailsR2dbcConnectionDetailsSpring中文文档

如果只想创建适用类型的子集,则可以使用 的属性。type@ServiceConnectionSpring中文文档

动态属性

服务连接的一个稍微冗长但也更灵活的替代方法是。 静态方法允许将动态属性值添加到 Spring 环境。@DynamicPropertySource@DynamicPropertySourceSpring中文文档

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 进行通信。Spring中文文档