Настройка и устранение сложного состояния базы данных с помощью Hibernate / Spring / JUnit

StackOverflow https://stackoverflow.com/questions/822846

  •  03-07-2019
  •  | 
  •  

Вопрос

У меня есть класс модульного тестирования, который требует довольно обширной настройки базы данных, прежде чем можно будет запустить отдельные методы тестирования. Эта настройка занимает много времени: по причинам, которые, как мы надеемся, не имеют отношения к рассматриваемому вопросу, мне нужно заполнять БД программно, а не из дампа SQL.

У меня проблема со сносом. Как я могу легко откатить все изменения, сделанные на этапе настройки БД?

В настоящее время я использую поддержку Hibernate + Spring Transactional Testing, так что мои отдельные методы тестирования заключены в транзакции.

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

Есть еще идеи? По сути, я ищу способ запустить мою настройку БД, запустить мои отдельные тесты (каждый из которых заключен в транзакцию, откат которой выполняется после выполнения), а затем откатить первоначальную настройку БД. Есть какие-нибудь идеи по поводу того, чтобы это работало в моде Hibernate / Spring / Junit? Есть ли в Hibernate "отбросить все таблицы"? эквивалентная команда?

Это было полезно?

Решение

Вы застряли с конкретным поставщиком базы данных? Если нет, вы можете использовать базу данных в памяти, например HSQLDB . Когда вы закончите с тестами, вы просто выбрасываете состояние. Это подходит только в том случае, если таблицы могут быть пустыми в начале набора тестов (то есть до вашей программной настройки).

Вам все еще нужно создавать таблицы, но если все аккуратно отображено с помощью Hibernate, вы можете использовать hbm2ddl для генерации ваших таблиц. Все, что вам нужно сделать, это добавить следующее в определение фабрики сеансов test :

<session-factory>
    ...
    <property name="hibernate.hbm2ddl.auto">create</property>
    ...
</session-factory>

Если это решение кажется применимым, я могу уточнить его.

Другие советы

Возможно, вы захотите посмотреть аннотацию @AfterClass для Junit 4. Эта аннотация будет запущена после завершения тестов.

http://cwiki.apache.org/DIRxDEV/junit4-primer.html

DNUnit должен помочь вам в этом. Вы можете создать отдельные наборы данных для каждого отдельного теста, если хотите.

DBUnit очень поможет в этом. Теоретически вы можете отключить автокоммиты на JDBC, но это может стать проблематичным. Наиболее очевидным решением является использование DBUnit для установки данных в известное состояние перед запуском тестов. Если по какой-то причине вам понадобятся ваши данные обратно после запуска тестов, вы можете посмотреть на @AfterClass в наборе, который запускает все ваши тесты, но обычно рекомендуется настроить ваши тесты, а затем запустить их, поэтому что если тест не пройден, это не только потому, что в нем не было предстательной среды из-за невозможности очистки другого теста. Вы гарантируете, что каждый тест устанавливает свою среду напрямую.

Одним из решений, которое вы можете рассмотреть, является использование " руководства " откат или компенсирующая транзакция в db teardown. Я полагаю (а если нет, то это должно быть тривиальное дополнение к вашим объектам Hibernate), все ваши объекты имеют атрибут datetime create, указывающий, когда они были ВСТАВЛЕНЫ в таблицу. Ваш метод настройки БД должен записывать время раньше, чем все остальное. Тогда у вас есть довольно простая процедура для удаления базы данных, чтобы удалить все сущности, которые были созданы после времени, записанного в настройке базы данных.

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

Если вы работаете с относительно небольшой базой данных и с СУБД, которая может выполнять ее резервное копирование / экспорт относительно быстро (например, MS SQL Server), вы можете рассмотреть возможность создания резервной копии базы данных перед тестами, а затем восстановить ее, когда все испытания завершены. Это позволяет вам настроить базу данных разработки / тестирования и использовать ее в качестве исходного состояния для всех ваших тестов.

Я сделал это с собственным JDBC, выполняя промежуточные тесты T-SQL «резервная база данных» и «восстановление базы данных», и это работало достаточно хорошо.

Однако этот подход зависит от наличия сервера СУБД на локальном компьютере (для разумной скорости), наличия достаточных привилегий (что не должно быть проблемой) и общего размера базы данных, не превышающего несколько десятков на МБ - по крайней мере, по моему опыту.

Есть ли причина, по которой у вас должно быть соединение с базой данных для запуска модульных тестов? Похоже, что вам может быть проще провести рефакторинг вашего класса, чтобы вы могли посмеяться над взаимодействием с базой данных. Вы можете макетировать классы (за некоторыми исключениями), а также интерфейсы с EasyMock (www.easymock.org).

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

Hibernate имеет изящную небольшую функцию, которая недостаточно документирована и неизвестна. Вы можете выполнить сценарий SQL во время создания SessionFactory сразу после создания схемы базы данных, чтобы импортировать данные в новую базу данных. Вам просто нужно добавить файл с именем import.sql в корневой каталог classpath и установить либо create, либо create-drop в качестве свойства hibernate.hbm2ddl.auto.

http://in.relation.to/Bloggers/RotterdamJBugAndHibernatesImportsql

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top