Spring Boot,ElasticSearch和TestContainers集成测试。连接被拒绝

时间:2019-01-03 18:44:38

标签: java spring-boot elasticsearch testcontainers

我创建了一个集成测试,用于从elasticsearch检索数据。

我正在使用testContainer的默认值,因此我的RestHighLevelClient应该可以访问测试容器,但是在尝试索引数据但运行时,我一直都遇到相同的异常(java.net.ConnecteException: Connection refused)通过命令

在本地创建docker映像
docker run -d --rm -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e "transport.host=127.0.0.1"  --name elastic docker.elastic.co/elasticsearch/elasticsearch:6.5.4

我的测试正常工作。

问题出在哪里,因为端口映射是相同的? 发生此异常的原因是什么?

我的测试:

@ExtendWith(SpringExtension.class)
@Testcontainers
@WebMvcTest
class FlowerResourceTest {

    @Container
    private ElasticsearchContainer esContainer = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:6.5.4");

    @Autowired
    private ElasticsearchConfiguration esConfig;

    @Autowired
    private FlowerService flowerService;

    private RestHighLevelClient client;


    @Test
    void test() throws IOException, InterruptedException {
        client = esConfig.client();

        var jsonFlower = "{\n" +
                "    \"name\": \"XXX\",\n" +
                "  \"color\" : \"red\"\n" +
                "}";
        IndexRequest indexRequest = new IndexRequest("flowers", "doc", "1")
                .source(jsonFlower, XContentType.JSON);


        assertTrue(esContainer.isRunning());
        client.index(indexRequest, RequestOptions.DEFAULT);


        var flowers = flowerService.findAll();


        assertTrue(flowers.size() > 0);

        DeleteRequest deleteRequest = new DeleteRequest("flowers", "doc", "1");

        client.delete(deleteRequest, RequestOptions.DEFAULT);
    }
}

3 个答案:

答案 0 :(得分:2)

如果我还记得的话,您可以使用以下命令请求暴露的端口:

esContainer.getMappedPort(ELASTICSEARCH_PORT);

Docker容器公开了一个随机可用的端口,因此请按照上述命令检查端口。使用该端口作为客户端。我的一个同事写了一篇有关此的博客文章,其中包含一些示例代码(如果您感兴趣的话): https://amsterdam.luminis.eu/2018/08/20/elasticsearch-instances-for-integration-testing/

答案 1 :(得分:0)

  1. 除非您进行其他配置,否则默认端口为9200。因此,如果您的客户端尝试连接到默认端口,则需要确保9200可用,以便可以在该端口上启动Testcontainers中的Elasticsearch。 / li>
  2. 我猜Elasticsearch没有足够的时间来启动。这是一个Java进程,可能需要一些时间-在我的计算机上大约20秒钟。您可能需要设置等待策略;像这样的东西:

    esContainer.setWaitStrategy(
            Wait.forHttp("/")
                    .forPort(9200)
                    .forStatusCode(200)
                    .withStartupTimeout(Duration.ofSeconds(60)));
    

答案 2 :(得分:0)

试试这样使用

    @Container
    private static ElasticsearchContainer elasticsearchContainer = new ElasticTestContainer();
    private RestHighLevelClient client;

    @BeforeClass
    public static void init(){
       elasticsearchContainer.start();
    }

    @Test
    void test() throws IOException, InterruptedException {
        RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(elasticsearchContainer.getHost(), 9200, "http"));
        client = new RestHighLevelClient(restClientBuilder);
        

        var jsonFlower = "{\n" +
                "    \"name\": \"XXX\",\n" +
                "  \"color\" : \"red\"\n" +
                "}";
        IndexRequest indexRequest = new IndexRequest("flowers", "doc", "1")
                .source(jsonFlower, XContentType.JSON);


        assertTrue(elasticsearchContainer.isRunning());
        client.index(indexRequest, RequestOptions.DEFAULT);


        var flowers = flowerService.findAll();


        assertTrue(flowers.size() > 0);

        DeleteRequest deleteRequest = new DeleteRequest("flowers", "doc", "1");

        client.delete(deleteRequest, RequestOptions.DEFAULT);
    }

ElasticTestContainer 类

public class ElasticTestContainer extends ElasticsearchContainer {

    private static final String DOCKER_ELASTIC = "docker.elastic.co/elasticsearch/elasticsearch:6.5.4";

    private static final String CLUSTER_NAME = "sample-cluster";

    private static final String ELASTIC_SEARCH = "elasticsearch";

    public ElasticTestContainer() {
        super(DOCKER_ELASTIC);
        this.addFixedExposedPort(9200, 9200);
        this.addFixedExposedPort(9300, 9300);
        this.addEnv(CLUSTER_NAME, ELASTIC_SEARCH);
    }
}