Обзор:
Я совершенно новичок в поисковом тестировании Elastic и собираюсь добавить правильные юнит-тесты. Совместимость проекта:
- Java 8
- Elasticsearch 6.2.4
- Проект использует низкоуровневый клиент отдыха для извлечения данных из ES
Более подробная информация о конфигурации ES приведена ниже:
import static java.net.InetAddress.getByName;
import static java.util.Arrays.stream;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.Objects;
import javax.inject.Inject;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import au.com.api.util.RestClientUtil;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Configuration
public class ElasticConfiguration implements InitializingBean{
@Value(value = "${elasticsearch.hosts}")
private String[] hosts;
@Value(value = "${elasticsearch.httpPort}")
private int httpPort;
@Value(value = "${elasticsearch.tcpPort}")
private int tcpPort;
@Value(value = "${elasticsearch.clusterName}")
private String clusterName;
@Inject
private RestClientUtil client;
@Bean
public RestHighLevelClient restHighClient() {
return new RestHighLevelClient(RestClient.builder(httpHosts()));
}
@Bean
@Deprecated
public RestClient restClient() {
return RestClient.builder(httpHosts()).build();
}
/**
* @return TransportClient
* @throws UnknownHostException
*/
@SuppressWarnings("resource")
@Bean
public TransportClient transportClient() throws UnknownHostException{
Settings settings = Settings.builder()
.put("cluster.name", clusterName).build();
return new PreBuiltTransportClient(settings).addTransportAddresses(transportAddresses());
}
@Override
public void afterPropertiesSet() throws Exception {
log.debug("loading search templates...");
try {
for (Map.Entry<String, String> entry : Constants.SEARCH_TEMPLATE_MAP.entrySet()) {
client.putInlineSearchTemplateToElasticsearch(entry.getKey(), entry.getValue());
}
} catch (Exception e) {
log.error("Exception has occurred in putting search templates into ES.", e);
}
}
private HttpHost[] httpHosts() {
return stream(hosts).map(h -> new HttpHost(h, httpPort, "http")).toArray(HttpHost[]::new);
}
private TransportAddress[] transportAddresses() throws UnknownHostException {
TransportAddress[] transportAddresses = stream(hosts).map(h -> {
try {
return new TransportAddress(getByName(h), tcpPort);
} catch (UnknownHostException e) {
log.error("Exception has occurred in creating ES TransportAddress. host: '{}', tcpPort: '{}'", h, tcpPort, e);
}
return null;
}).filter(Objects::nonNull).toArray(TransportAddress[]::new);
if (transportAddresses.length == 0) {
throw new UnknownHostException();
}
return transportAddresses;
}
}
Проблема:
Я не знаю, как Mock ES или как тестировать ES без запуска автономной ES на моей машине. Пожалуйста, используйте следующий класс в качестве примера и дайте мне знать, как я могу написать контрольный пример (модульный тест без интеграции) для метода getSearchResponse
:
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.NoNodeAvailableException;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.script.mustache.SearchTemplateRequestBuilder;
import org.elasticsearch.search.Scroll;
import org.elasticsearch.search.aggregations.Aggregation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Repository;
@Slf4j
@Repository
@NoArgsConstructor
public abstract class NewBaseElasticsearchRepository {
@Autowired
protected NewIndexLocator newIndexLocator;
@Value(value = "${elasticsearch.client.timeout}")
private Long timeout;
@Autowired
protected TransportClient transportClient;
@Autowired
protected ThresholdService thresholdService;
@Autowired
protected MessageSource messageSource;
/**
* @param script the name of the script to be executed
* @param templateParams a map of the parameters to be sent to the script
* @param indexName the index to target (an empty indexName will search all indexes)
*
* @return a Search Response object containing details of the request results from Elasticsearch
*
* @throws NoNodeAvailableException thrown when the transport client cannot connect to any ES Nodes (or Coordinators)
* @throws Exception thrown for all other request errors such as parsing and non-connectivity related issues
*/
protected SearchResponse getSearchResponse(String script, Map<String, Object> templateParams, String... indexName) {
log.debug("transport client >> index name --> {}", Arrays.toString(indexName));
SearchResponse searchResponse;
try {
searchResponse = new SearchTemplateRequestBuilder(transportClient)
.setScript(script)
.setScriptType(ScriptType.STORED)
.setScriptParams(templateParams)
.setRequest(new SearchRequest(indexName))
.execute()
.actionGet(timeout)
.getResponse();
} catch (NoNodeAvailableException e) {
log.error(ELASTIC_SEARCH_EXCEPTION_NOT_FOUND, e.getMessage());
throw new ElasticSearchException(ELASTIC_SEARCH_EXCEPTION_NOT_FOUND);
} catch (Exception e) {
log.error(ELASTIC_SEARCH_EXCEPTION, e.getMessage());
throw new ElasticSearchException(ELASTIC_SEARCH_EXCEPTION);
}
log.debug("searchResponse ==> {}", searchResponse);
return searchResponse;
}
Итак, я был бы признателен, если бы вы взглянули на пример класса и поделились со мной вашими подлинными решениями о том, как я могу высмеивать TransportClient
и получить правильный ответ от SearchResponse
объекта.
Примечание:
- Я пытался использовать
ESTestCase
из org.elasticsearch.test:framework:6.2.4
, но столкнулся с проблемой jar hell
и не смог ее решить. В то же время я не смог найти никаких документов, связанных с этим или модульным тестированием Java ES в целом.