简体   繁体   English

Spring boot、ElasticSearch 和 TestContainers 集成测试。 拒绝连接

[英]Spring boot, ElasticSearch and TestContainers integration tests. Connection refused

I create an integration test for retrieving data from elasticsearch.我创建了一个用于从 elasticsearch 检索数据的集成测试。

I am using default values for the testContainer so my RestHighLevelClient should have access to the test container but all the time I am getting the same exception ( java.net.ConnecteException: Connection refused ) when I am trying to index data, but when I run my locally the docker image by command我正在使用 testContainer 的默认值,因此我的 RestHighLevelClient 应该可以访问测试容器,但是当我尝试索引数据时,我总是得到相同的异常( java.net.ConnecteException: Connection refused denied ),但是当我运行时我通过命令在本地获取 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

my test works correctly.我的测试工作正常。

Where is the problem, because the port mapping is the same?问题出在哪里,因为端口映射是一样的? What is the reason of this exception?这个异常的原因是什么?

My test:我的测试:

@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);
    }
}

If I remember well, you can ask for the exposed port using the following command:如果我没记错的话,你可以使用以下命令请求暴露的端口:

esContainer.getMappedPort(ELASTICSEARCH_PORT);

The Docker container exposes a random available port, so check the port as with the mentioned command. Docker 容器公开了一个随机可用端口,因此请使用上述命令检查该端口。 Use that port for the client.将该端口用于客户端。 A colleague of mine wrote a blog post about this with some sample code if you are interested: https://www.luminis.eu/blog/search-en/elasticsearch-instances-for-integration-testing/如果您有兴趣,我的一位同事用一些示例代码写了一篇关于此的博客文章: https ://www.luminis.eu/blog/search-en/elasticsearch-instances-for-integration-testing/

  1. Unless you configure it differently, the default port is 9200. So if your client is trying to connect to the default, you need to make sure that 9200 is available so that Elasticsearch in Testcontainers can be started up on that port.除非您以不同方式配置它,否则默认端口是 9200。因此,如果您的客户端尝试连接到默认端口,则需要确保 9200 可用,以便可以在该端口上启动 Testcontainers 中的 Elasticsearch。
  2. I would guess that Elasticsearch hasn't had enough time to start up.我猜想 Elasticsearch 没有足够的时间启动。 It's a Java process and might need some time — on my machine around 20s.这是一个 Java 进程,可能需要一些时间——在我的机器上大约 20 多岁。 You'll probably want to set a wait strategy;您可能需要设置等待策略; something like this:像这样的东西:

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

Try using it this way尝试以这种方式使用它

    @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 class 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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Spring Boot测试。 以编程方式初始化数据库 - Spring Boot tests. Initilize database programatically 如何使用 Spring Boot、R2DBC 和 TestContainers(Spanner 模拟器)为 Spanner 集成测试提供凭据 - How to provide credentials for Spanner integration tests with Spring Boot, R2DBC and TestContainers (Spanner Emulator) Spring 数据 Elasticsearch 在SpringBoot中使用Testcontainers进行集成测试 - Spring Data Elasticsearch integration test using Testcontainers in SpringBoot 如何在 spring 启动集成测试期间正确连接到测试容器 redis? - How to connect to testcontainers redis correctly during spring boot integration test? 使用 Testcontainers/Localstack 和 Spring 进行集成测试 Boot:为临时文件设置目录 - Integration testing with Testcontainers/Localstack and Spring Boot: Set directory for temporary files JUnit 5 和 inheritance 具有不同的扩展,用于 Spring 引导集成测试与 TestContainers - JUnit 5 and inheritance with different extensions for Spring Boot Integration test with TestContainers JedisPool 连接拒绝 Spring Boot - JedisPool Connection Refused Spring Boot Elasticsearch Spring启动集成测试 - Elasticsearch Spring boot integration test 与PowerMock和Spring Boot的集成测试 - Integration Tests with PowerMock and Spring Boot 带弹簧启动的Proguard-集成测试 - Proguard with spring boot - integration tests
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM