Как писать модульные тесты java для построения запросов elasticsearch?

#java #unit-testing #elasticsearch #junit #elasticsearch-query

#java #модульное тестирование #elasticsearch #junit #elasticsearch-запрос

Вопрос:

Итак, я пишу модульные тесты java (mockito) для класса, который создает запросы elasticsearch. Текущий способ, которым это делается, довольно неаккуратен, обновлять тесты при каждом внесении изменений — такая утомительная работа. К сожалению, похоже, что официальная документация ES для тестирования Java мертва, поэтому я надеюсь, что у кого-нибудь есть несколько советов относительно того, как лучше написать мои тесты.

Исходный класс — довольно сложный запрос, и модульные тесты, по сути, создают экземпляр класса и сериализуют его в JsonNode. Затем выполняется обход JsonNode и утверждается ожидаемое значение. Кажется, что этот стиль тестирования граничит с жестким кодом. Вот пример теста:

 @Test
public void toQueryBuilder_initialQuery() {
  // queryValue defined here.
  JsonNode result = QueryBuilderSerialization.toJsonNode(new QueryConstraintA(queryValue)
                                             .toQueryBuilder());
  // assert expected queries
  assertEquals(EXPECTED_MIN, result
            .get("bool")
            .get("filter").get(0)
            .get("function_score")
            .get("min_score")
            .asInt());

  assertEquals(EXPECTED_LOWER_BOUND, countQuery.get(7)
            .get("function_score")
            .get("query")
            .get("nested")
            .get("query")
            .get("constant_score")
            .get("filter")
            .get("bool")
            .get("filter").get(0)
            .get("bool")
            .get("filter").get(0)
            .get("bool")
            .get("should").get(0)
            .get("range")
            .get(RANGE_FIELD_NAME)
            .get("from")
            .asInt());
}
  

В этом стиле написано примерно 1000 строк тестов, только в этом файле. Итак, вы можете себе представить, насколько сложно изменять исходный запрос. У кого-нибудь есть предложения относительно того, как это можно сделать лучше? Заранее спасибо за любое время, потраченное на это.

Ответ №1:

Я не рекомендую писать тесты такого рода. Вместо проверки того, что запрос выглядит нормально, вы действительно хотите проверить, возвращает ли он правильный вывод при запуске. Это намного больше работы, но в нашем магазине мы выполняем фактические запросы к локальному экземпляру Elasticsearch в Docker. Это проверяет, что запросы не искажены и что они действительно выполняют то, что должны. Это также делает их более устойчивыми, когда кто-то рефакторирует запрос (для улучшения задержки), не внося никаких изменений в логику.

Комментарии:

1. Я вроде как хочу провести интеграционный тест, но я действительно не хочу запускать локальный экземпляр Docker на сервере сборки, что на самом деле не является лучшим решением для аппаратного обеспечения. Прошел год с момента вашего сообщения, нашли какие-либо другие хорошие решения для тестирования клиента?

2. Не совсем 🙂 Я все еще думаю, что локальный ES docker — это правильный путь. Другой вариант — где-нибудь разместить небольшой сервер разработки ES. В настройке теста сгенерируйте индекс со случайным именем, поместите в него некоторые данные и удалите его при удалении. Поскольку имена тестов являются случайными, вы запускаете несколько человек, и они не будут конфликтовать друг с другом. Однако, если сервер разработки не работает, CI будет нарушен для всех, поэтому я предпочитаю вариант локального docker.