2

I create an integration test for retrieving data from 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

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

3 Answers 3

2

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. 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/

Sign up to request clarification or add additional context in comments.

3 Comments

Is there a possibility to set up this port to the constant number?
They see it as a bad practice to use fixed ports. If you want a fixed port, you can use the specific container FixedHostPortGenericContainer. If you want this with the elastic container you can subclass the elastic container and add this behavior.
0
  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.
  2. I would guess that Elasticsearch hasn't had enough time to start up. It's a Java process and might need some time — on my machine around 20s. You'll probably want to set a wait strategy; something like this:

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

1 Comment

If you look into constructor implementation of ElasticseachContainer then you can see that StartupTime is set to 120 seconds.
0

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

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.