Switch to Testcontainers for Elasticsearch examples.

See #636
This commit is contained in:
Mark Paluch
2022-04-26 11:30:09 +02:00
committed by Greg L. Turnquist
parent b043239eb2
commit 13c0dea55c
14 changed files with 107 additions and 177 deletions

View File

@@ -17,11 +17,6 @@
<dependencies>
<dependency>
<groupId>org.springframework.data.examples</groupId>
<artifactId>spring-data-elasticsearch-example-utils</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>

View File

@@ -1 +0,0 @@
#spring.elasticsearch.rest.uris=http://localhost:9200

View File

@@ -0,0 +1,12 @@
<Configuration status="INFO">
<Appenders>
<Console name="LogToConsole" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="LogToConsole"/>
</Root>
</Loggers>
</Configuration>

View File

@@ -17,8 +17,6 @@ package example.springdata.elasticsearch.conference;
import static org.assertj.core.api.Assertions.*;
import example.springdata.elasticsearch.util.EnabledOnElasticsearch;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@@ -27,12 +25,17 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.elasticsearch.ElasticsearchContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;
/**
* Test case to show Spring Data Elasticsearch functionality.
@@ -43,13 +46,25 @@ import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
* @author Prakhar Gupta
*/
@SpringBootTest(classes = ApplicationConfiguration.class)
@EnabledOnElasticsearch
@Testcontainers
class ElasticsearchOperationsTest {
private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
@Autowired
ElasticsearchOperations operations;
@Container //
private static ElasticsearchContainer container = new ElasticsearchContainer(
DockerImageName.parse("docker.elastic.co/elasticsearch/elasticsearch:7.17.2")) //
.withPassword("foobar") //
.withReuse(true);
@DynamicPropertySource
static void setProperties(DynamicPropertyRegistry registry) {
registry.add("spring.elasticsearch.uris", () -> "http://" + container.getHttpHostAddress());
registry.add("spring.elasticsearch.username", () -> "elastic");
registry.add("spring.elasticsearch.password", () -> "foobar");
}
@Autowired ElasticsearchOperations operations;
@Test
void textSearch() throws ParseException {

View File

@@ -16,7 +16,6 @@
<url>https://github.com/spring-projects/spring-data-elasticsearch</url>
<modules>
<module>util</module>
<module>example</module>
<module>reactive</module>
</modules>
@@ -44,6 +43,18 @@
</exclusions>
</dependency>
<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>
</dependencies>
</project>

View File

@@ -17,11 +17,6 @@
<dependencies>
<dependency>
<groupId>org.springframework.data.examples</groupId>
<artifactId>spring-data-elasticsearch-example-utils</artifactId>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>

View File

@@ -19,7 +19,6 @@ import reactor.test.StepVerifier;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@@ -27,12 +26,11 @@ import javax.annotation.PreDestroy;
import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
@@ -43,13 +41,13 @@ import org.springframework.data.elasticsearch.core.geo.GeoPoint;
class ApplicationConfiguration {
@Autowired ReactiveElasticsearchOperations operations;
@Autowired RestHighLevelClient client;
@Autowired ConferenceRepository repository;
@PreDestroy
public void deleteIndex() {
try {
RestClients.create(ClientConfiguration.localhost()).rest().indices()
.delete(new DeleteIndexRequest("conference-index"), RequestOptions.DEFAULT);
client.indices().delete(new DeleteIndexRequest("conference-index"), RequestOptions.DEFAULT);
} catch (IOException | ElasticsearchStatusException e) {
// just ignore it
}
@@ -59,8 +57,7 @@ class ApplicationConfiguration {
public void insertDataSample() {
try {
RestClients.create(ClientConfiguration.localhost()).rest().indices()
.create(new CreateIndexRequest("conference-index"), RequestOptions.DEFAULT);
client.indices().create(new CreateIndexRequest("conference-index"), RequestOptions.DEFAULT);
} catch (IOException | ElasticsearchStatusException e) {
// just ignore it
}
@@ -79,7 +76,6 @@ class ApplicationConfiguration {
.location(new GeoPoint(50.0646501D, 19.9449799)).build());
// Remove all documents
repository.deleteAll().then(repository.saveAll(documents).then())
.as(StepVerifier::create).verifyComplete();
repository.deleteAll().then(repository.saveAll(documents).then()).as(StepVerifier::create).verifyComplete();
}
}

View File

@@ -1 +0,0 @@
spring.data.elasticsearch.client.reactive.endpoints=localhost:9200

View File

@@ -0,0 +1,12 @@
<Configuration status="INFO">
<Appenders>
<Console name="LogToConsole" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="LogToConsole"/>
</Root>
</Loggers>
</Configuration>

View File

@@ -17,7 +17,6 @@ package example.springdata.elasticsearch.conference;
import static org.assertj.core.api.Assertions.*;
import example.springdata.elasticsearch.util.EnabledOnElasticsearch;
import reactor.test.StepVerifier;
import java.text.ParseException;
@@ -31,6 +30,13 @@ import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperatio
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.elasticsearch.ElasticsearchContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;
/**
* Test case to show Spring Data Elasticsearch functionality.
@@ -38,14 +44,26 @@ import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
* @author Christoph Strobl
* @author Prakhar Gupta
*/
@EnabledOnElasticsearch
@SpringBootTest(classes = ApplicationConfiguration.class)
@Testcontainers
class ReactiveElasticsearchOperationsTest {
private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
@Autowired
ReactiveElasticsearchOperations operations;
@Container //
private static ElasticsearchContainer container = new ElasticsearchContainer(
DockerImageName.parse("docker.elastic.co/elasticsearch/elasticsearch:7.17.2")) //
.withPassword("foobar") //
.withReuse(true);
@DynamicPropertySource
static void setProperties(DynamicPropertyRegistry registry) {
registry.add("spring.elasticsearch.uris", () -> "http://" + container.getHttpHostAddress());
registry.add("spring.elasticsearch.username", () -> "elastic");
registry.add("spring.elasticsearch.password", () -> "foobar");
}
@Autowired ReactiveElasticsearchOperations operations;
@Test
void textSearch() {

View File

@@ -17,7 +17,6 @@ package example.springdata.elasticsearch.conference;
import static org.assertj.core.api.Assertions.*;
import example.springdata.elasticsearch.util.EnabledOnElasticsearch;
import reactor.test.StepVerifier;
import java.text.ParseException;
@@ -27,6 +26,13 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.elasticsearch.ElasticsearchContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;
/**
* Test case to show reactive Spring Data Elasticsearch repository functionality.
@@ -34,14 +40,26 @@ import org.springframework.boot.test.context.SpringBootTest;
* @author Christoph Strobl
* @author Prakhar Gupta
*/
@EnabledOnElasticsearch
@SpringBootTest(classes = ApplicationConfiguration.class)
@Testcontainers
class ReactiveElasticsearchRepositoryTest {
private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
@Autowired
ConferenceRepository repository;
@Container //
private static ElasticsearchContainer container = new ElasticsearchContainer(
DockerImageName.parse("docker.elastic.co/elasticsearch/elasticsearch:7.17.2")) //
.withPassword("foobar") //
.withReuse(true);
@DynamicPropertySource
static void setProperties(DynamicPropertyRegistry registry) {
registry.add("spring.elasticsearch.uris", () -> "http://" + container.getHttpHostAddress());
registry.add("spring.elasticsearch.username", () -> "elastic");
registry.add("spring.elasticsearch.password", () -> "foobar");
}
@Autowired ConferenceRepository repository;
@Test
void textSearch() {

View File

@@ -1,35 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.data.examples</groupId>
<artifactId>spring-data-elasticsearch-examples</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
</parent>
<artifactId>spring-data-elasticsearch-example-utils</artifactId>
<name>Spring Data Elasticsearch - Example Utilities</name>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-commons</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1,57 +0,0 @@
/*
* Copyright 2021-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.elasticsearch.util;
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
import org.junit.jupiter.api.extension.ExecutionCondition;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.platform.commons.support.AnnotationSupport;
import org.springframework.http.HttpMethod;
import org.springframework.web.client.RestTemplate;
/**
* {@link ExecutionCondition} evaluating {@link EnabledOnElasticsearch @EnableOnElasticsearch}.
*
* @author Christoph Strobl
* @author Prakhar Gupta
*/
class ElasticsearchAvailableCondition implements ExecutionCondition {
@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext extensionContext) {
var annotation = AnnotationSupport.findAnnotation(extensionContext.getElement(),
EnabledOnElasticsearch.class);
return annotation.map(EnabledOnElasticsearch::url) //
.map(ElasticsearchAvailableCondition::checkServerRunning) //
.orElse(ConditionEvaluationResult.enabled("Enabled by default"));
}
private static ConditionEvaluationResult checkServerRunning(String url) {
var template = new RestTemplate();
try {
var entity = template.exchange(url, HttpMethod.HEAD, null, byte[].class);
return ConditionEvaluationResult
.enabled("Successfully connected to Elasticsearch server: " + entity.getStatusCode());
} catch (RuntimeException e) {
return ConditionEvaluationResult.disabled("Elasticsearch unavailable at " + url + "; " + e.getMessage());
}
}
}

View File

@@ -1,48 +0,0 @@
/*
* Copyright 2021-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.elasticsearch.util;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.extension.ExtendWith;
/**
* {@code @EnableOnElasticsearch} is used to signal that the annotated test class or test method is only
* <em>enabled</em> if Elasticsearch is available at {@link #url()}.
* <p>
* When applied at the class level, all test methods within that class will be enabled if Elasticsearch is available.
* <p>
* If a test method is disabled via this annotation, that does not prevent the test class from being instantiated.
* Rather, it prevents the execution of the test method and method-level lifecycle callbacks such as {@code @BeforeEach}
* methods, {@code @AfterEach} methods, and corresponding extension APIs.
*
* @author Prakhar Gupta
* @author Mark Paluch
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@ExtendWith(ElasticsearchAvailableCondition.class)
public @interface EnabledOnElasticsearch {
/**
* URL pointing at the Elasticsearch instance to check.
*/
String url() default "http://localhost:9200";
}