Настройка и устранение сложного состояния базы данных с помощью Hibernate / Spring / JUnit
Вопрос
У меня есть класс модульного тестирования, который требует довольно обширной настройки базы данных, прежде чем можно будет запустить отдельные методы тестирования. Эта настройка занимает много времени: по причинам, которые, как мы надеемся, не имеют отношения к рассматриваемому вопросу, мне нужно заполнять БД программно, а не из дампа 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. Эта аннотация будет запущена после завершения тестов.
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