Как сделать модульные тесты для классов DAO менее хрупкими при отсутствии базы статических тестов? - PullRequest
2 голосов
/ 21 сентября 2011

Вот сканарио:

Я работаю над объектом DAO, который использует API критериев гибернации для формирования ряда сложных запросов для выполнения определенных задач в базе данных (например, поиск по ключевым словам в нескольких полях).

Нам нужно провести модульное тестирование, чтобы убедиться, что сгенерированный запрос корректен для различных сценариев.Один из способов его проверки, который может быть предпочтительным, состоит в том, чтобы проверить правильность создания критериев гибернации, проверив его в конце и посмеявшись над взаимодействием с базой данных.Однако это нежелательно, так как, во-первых, это своего рода обман (он просто дублирует то, что будет делать код), а также он не проверяет, приводит ли сам критерий к спячке или когда он попадает в базу данных, это вызывает проблемы.

Опция, которую нужно использовать, - это запустить запрос к тестовой базе данных.Однако по историческим причинам нет статической тестовой базы данных (например, код, который будет проверяться как часть кода), и сфера полномочий моего проекта не позволяет мне приступить к ее созданию, нам приходится довольствоваться тестированием на соответствиеразделяемая база данных разработки, которая периодически обновляется производственными данными.

Когда эти обновления происходят, данные, лежащие в основе тестов, тоже могут измениться, и это сделает наши модульные тесты хрупкими.Мы можем преодолеть это, не используя точные числа в тестах, но это не совсем адекватное тестирование таким образом.

Тогда возникает вопрос: что люди делают в подобных случаях, чтобы сделать тесты менее хрупкими?Один из вариантов, который я имею в виду, - запустить собственный SQL, который выполняет тот же запрос (поведенчески - он не должен совпадать с запросом, сгенерированным hibernate), чтобы получить ожидаемое число, а затем запустить версию DAO, чтобы увидетьесли это соответствует.Таким образом, поведение запроса всегда может быть реализовано в исходном собственном SQL-коде, и вы всегда будете иметь правильные числа.

Буду весьма признателен за любые отзывы об этой или других идеях относительно управления этой ситуацией.

A.

ОБНОВЛЕНИЕ:

Что касается предложений hsqldb / h2 / derby, я знаком с ними, но компания не готовапросто идите по этому пути пока что, и делать это по частям только на одном тестовом примере не подойдет.

Что касается моего более раннего предложения, я хотел бы подробнее остановиться на этом - рассмотрим этот сценарий:

Я хочу убедиться, что мой относительно сложный поиск по ключевым словам возвращает 2100 соответствий для "Джона Смита".

Чтобы найти ожидаемое число, я бы проанализировал свою базу данных и выяснил число, используя запрос SQL,Какова обратная сторона того, что этот запрос является частью теста, так что вы всегда будете знать, что вы тестируете поведение критериев?

Таким образом, в основном вопрос заключается в следующем: если по какой-то причине вы не могли иметьстатический набор данных для тестирования, как бы вы выполняли интеграционные тесты нехрупким способом?

Ответы [ 3 ]

6 голосов
/ 21 сентября 2011

Одним из подходов может быть использование базы данных в памяти, такой как Apache Derby или HSQLDB , и предварительное заполнение ее данными перед началом теста с использованием DBUnit .

ОБНОВЛЕНИЕ : Вот хорошая статья о подходе.

5 голосов
/ 21 сентября 2011

Я согласен с Андреем и Бедвиром, что лучший подход в долгосрочной перспективе - это создание базы данных hsqldb специально для тестирования.Если у вас нет возможности сделать это, то ваше решение кажется подходящим.Вы не можете проверить все, но вы тоже не хотите ничего проверять.Я несколько раз использовал этот подход для тестирования веб-сервисов на базе интеграционных баз данных и т. Д. Но помните, что эта база данных также должна поддерживаться, если вы добавляете новые столбцы и т. Д.

Вы должны решить, что вам 'пытаюсь проверить.Вы не хотите проверять спящий режим, вы не хотите проверять, что база данных дает то, о чем вы просили (в терминах SQL).В ваших тестах вы можете предположить, что hibernate работает, как и база данных.

Вы говорите:

Нам нужно выполнить модульное тестирование, чтобы убедиться, что сгенерированный запрос корректен для различныхсценарии.Один из способов его проверки, который может быть предпочтительным, состоит в том, чтобы проверить правильность создания критериев гибернации, проверив его в конце и посмеявшись над взаимодействием с базой данных.Однако это нежелательно, так как, во-первых, это своего рода обман (он просто дублирует то, что будет делать код), а также он не проверяет, приводит ли сам критерий к гибернации или когда он попадает в базу данных, это вызывает проблемы.

Почему гибернация должна отрицать по критериям, которые вы ей даете?Потому что вы даете это неправильные критерии.Это не проблема гибернации, а кода, создающего критерии.Вы можете проверить это без базы данных.

У него есть проблемы, когда он попадает в базу данных?В общем, Hibernate создает sql, который соответствует критериям и диалекту базы данных, который вы ему задаете, поэтому опять проблема с критериями.

База данных не соответствует ожидаемому hibernate?Теперь вы проверяете, что критерии и база данных выровнены.Для этого вам нужна база данных.Но вы больше не проверяете критерии, вы проверяете, что все выровнено, иного рода тест.

Так что, на самом деле, мне кажется, что вы проводите интеграционный тест, что в целомЦепочка от критериев к структуре базы данных работ.Это совершенно корректный тест.

Итак, в моих тестах я создаю другое соединение с базой данных (jdbc) для получения информации.Я выполняю SQL, чтобы получить количество строк и т. Д., Или проверяю, что вставка произошла.

Я думаю, что ваш подход является совершенно верным.

3 голосов
/ 21 сентября 2011

Однако по историческим причинам нет статической тестовой базы данных (например, той, в которой код должен быть зарегистрирован как часть кода), и сфера полномочий моего проекта не позволяет мне приступить к созданию на

Все, что вам нужно сделать, это запустить H2 или аналогичный - вставьте в него несколько объектов и выполните тесты интеграции.Сделав это для нескольких тестов, вы сможете извлечь утилиту настройки данных, которая создает схему с некоторыми тестовыми данными, которые можно использовать для всех интеграционных тестов, если вы чувствуете необходимость.

...