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);
    }
}
Ice
  • 1,783
  • 4
  • 26
  • 52

3 Answers3

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/

Jettro Coenradie
  • 4,735
  • 23
  • 31
  • Is there a possibility to set up this port to the constant number? – Ice Jan 06 '19 at 22:11
  • 1
    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. – Jettro Coenradie Jan 07 '19 at 07:58
  • 1
    New url https://www.luminis.eu/blog/search-en/elasticsearch-instances-for-integration-testing/ – enyoucky Jul 14 '22 at 17:34
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)));
    
xeraa
  • 10,456
  • 3
  • 33
  • 66
  • If you look into constructor implementation of ElasticseachContainer then you can see that StartupTime is set to 120 seconds. – Ice Jan 06 '19 at 20:39
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);
    }
}
Saif Haider
  • 511
  • 1
  • 5
  • 16