You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于嵌入式Elasticsearch的Spring Boot REST服务集成测试改造问询

实现Spring Boot集成测试用嵌入式Elasticsearch的方案

刚好我之前帮团队做过类似的改造,给你梳理两种靠谱的实现方案,都能让你的集成测试彻底脱离对外部Elasticsearch实例的依赖,不用再担心测试环境的ES集群可用性问题。


方案一:纯Java嵌入式Elasticsearch(Flapdoodle)

这种方案不需要依赖Docker,完全用Java代码启动嵌入式ES实例,适合快速运行本地测试。

1. 添加测试依赖

在你的Maven/Gradle中加入测试范围的依赖(版本尽量和生产ES版本匹配):

<!-- Maven -->
<dependency>
    <groupId>de.flapdoodle.embed</groupId>
    <artifactId>de.flapdoodle.embed.es</artifactId>
    <version>3.4.1</version> <!-- 对应ES 8.x版本,可按需调整 -->
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

2. 编写测试专用配置类

创建一个仅在测试环境生效的配置类,覆盖生产环境的ES客户端配置:

@TestConfiguration
public class EmbeddedEsConfig {

    @Bean
    public RestHighLevelClient elasticsearchClient() throws IOException {
        // 配置嵌入式ES实例
        EsVersion version = EsVersion.V_8_11_3;
        Settings settings = Settings.builder()
                .put("cluster.name", "test-es-cluster")
                .put("http.port", "9201")
                .put("discovery.type", "single-node")
                .build();

        // 启动嵌入式ES
        EmbeddedElasticsearchServerFactory factory = new EmbeddedElasticsearchServerFactory(settings, version);
        factory.start();

        // 创建连接到嵌入式ES的客户端
        ClientConfiguration clientConfig = ClientConfiguration.builder()
                .connectedTo("localhost:9201")
                .build();

        return RestClients.create(clientConfig).rest();
    }

    // 如果用Spring Data Elasticsearch的RestTemplate,也可以一并配置
    @Bean
    public ElasticsearchRestTemplate elasticsearchRestTemplate(RestHighLevelClient client) {
        return new ElasticsearchRestTemplate(client);
    }
}

3. 改造测试类

在你的集成测试类中导入这个测试配置,并添加测试前后的索引清理逻辑,保证测试隔离:

@SpringBootTest
@Import(EmbeddedEsConfig.class)
class DataStorageServiceTest {

    @Autowired
    private DataStorageService storageService; // 你的业务服务类

    @Autowired
    private ElasticsearchRestTemplate restTemplate;

    @BeforeEach
    void setUp() {
        // 提前创建测试索引(假设你的实体类是DataEntity)
        restTemplate.indexOps(DataEntity.class).create();
        restTemplate.indexOps(DataEntity.class).putMapping();
    }

    @AfterEach
    void tearDown() {
        // 测试结束后删除索引,避免污染下一次测试
        restTemplate.indexOps(DataEntity.class).delete();
    }

    @Test
    void shouldSaveDataToEmbeddedEsSuccessfully() {
        // 构造测试数据
        DataEntity testData = new DataEntity("test-id", "测试内容", LocalDateTime.now());
        // 调用业务服务保存
        storageService.saveData(testData);
        // 查询验证
        DataEntity retrievedData = restTemplate.get("test-id", DataEntity.class);
        
        assertNotNull(retrievedData);
        assertEquals("测试内容", retrievedData.getContent());
    }
}

方案二:Testcontainers Elasticsearch容器(更贴近生产)

如果你的测试需要更贴近生产环境的ES行为(比如完整的安全机制、集群特性),可以用Testcontainers启动真实的ES容器,这种方案需要本地或CI环境有Docker支持。

1. 添加Testcontainers依赖

<!-- Maven -->
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>elasticsearch</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>junit-jupiter</artifactId>
    <scope>test</scope>
</dependency>

2. 编写测试配置

@TestConfiguration
public class TestcontainersEsConfig {

    @Bean
    public ElasticsearchContainer elasticsearchContainer() {
        // 指定ES镜像版本,和生产一致
        ElasticsearchContainer container = new ElasticsearchContainer(
                DockerImageName.parse("docker.elastic.co/elasticsearch/elasticsearch:8.11.3")
        );
        // 关闭安全设置(或者配置认证,根据需求)
        container.addEnv("xpack.security.enabled", "false");
        container.addEnv("discovery.type", "single-node");
        container.start();
        return container;
    }

    @Bean
    public RestHighLevelClient elasticsearchClient(ElasticsearchContainer container) {
        ClientConfiguration clientConfig = ClientConfiguration.builder()
                .connectedTo(container.getHttpHostAddress())
                .build();
        return RestClients.create(clientConfig).rest();
    }
}

3. 测试类改造

和方案一类似,导入配置后进行测试,Testcontainers会自动管理容器的启动和销毁,不需要手动停止ES实例。


关键注意事项

  • 版本匹配:嵌入式ES/Testcontainers镜像的版本必须和生产环境的ES版本尽量一致,避免因为API语法差异导致测试通过但生产报错。
  • 测试隔离:每次测试后一定要清理索引数据或删除索引,防止不同测试用例之间的数据污染。
  • 配置覆盖:可以通过application-test.yml配置ES地址,替代硬编码,比如:
    spring:
      elasticsearch:
        rest:
          uris: http://localhost:9201
    
  • ES8+安全设置:如果用ES8+版本,默认开启安全认证,需要在配置中添加用户名密码(Testcontainers的ES容器默认用户名是elastic,密码可以通过container.getPassword()获取)。

内容的提问来源于stack exchange,提问作者user2796509

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:25:52