Лучшие практики JUnit Test на основе JPA
Это немного странный вопрос, но он беспокоит меня уже несколько месяцев. Я создал веб-приложение на основе JPA, используя Wicket + Hibernate (построенный с помощью Maven), и хочу протестировать слой DAO напрямую. Я создал специальный файл src/test/resources/META-INF/persistence.xml, который я использовал для тестирования, но столкнулся с конфликтами с WTP и т.п. Чтобы обойти эти проблемы, я создал отдельный тестовый проект, в котором тестируются модульные тесты. Есть ли лучший способ управлять модульными тестами для проекта JPA без поединков между файлами сохранения?
Добавление: могут ли другие тестовые рамки (например, TestNG) сделать это проще?
Ответы
Ответ 1
Вы можете попробовать mockito. Тест работает следующим образом:
Вы используете mockito для "реализации" EntityManager
. Вместо реального кода вы используете методы mockito, чтобы сказать "если приложение вызывает getReference()
, а затем вернет этот объект". В фоновом режиме mockito создаст экземпляр прокси, который перехватывает вызовы метода Java и возвращает указанные вами значения. Вызовы других методов вернут null
.
Издевательские вещи, такие как createQuery()
, работают одинаково, но сначала вам нужно создать макет Query
, а затем использовать тот же подход, что и в getReference()
(вернуть макет запроса).
Поскольку вы не используете реальный EM, вам не нужен реальный persistence.xml
.
Более простым решением было бы, если бы вы могли установить какое-либо свойство, чтобы изменить имя файла persistence.xml
, но я не думаю, что это возможно.
Некоторые другие ссылки, которые могут помочь:
Ответ 2
Мы используем два файла persistence.xml для создания и тестирования времени выполнения, но это проблема, связанная с classpath (мы используем Eclipse, но не сильно полагаемся на WTP-плагины). Единственное различие между ними состоит в том, что производственная версия не содержит определения сущностей.
Мы не используем mocking framework для тестирования JPA, так как это не добавит никакого значения нашим испытаниям. Тесты действительно обеспечивают реальный доступ к данным с помощью JPA, который ведет переговоры с базой данных PostgreSQL.
Наш подход к испытаниям основан на Spring тестовой структуре для уровня persistence: in-transaction testing. Наше приложение Spring, но этот подход одинаково применим для любых приложений, которые хотят использовать тестовые классы Spring. Суть в том, что каждый тест проходит в рамках одной транзакции, которая никогда не совершается, а в конце (в tearDown) она автоматически откатывается назад. Это решает проблему загрязнения данных и тестовой зависимости очень красивым и ненавязчивым и прозрачным способом.
Структура тестирования Spring является гибкой, позволяющей проводить тестирование с несколькими транзакциями, но это особые случаи, которые составляют не более 10% тестов.
Мы по-прежнему используем устаревшую поддержку JUnit 3.8, но новый Spring TestContext Framework для JUnit 4 выглядит очень привлекательно.
Для настройки тестовых данных в транзакции мы используем внутренний класс утилиты, который создает бизнес-объекты. Так как он разделял между всеми тестами накладные расходы, чтобы поддерживать и поддерживать его, он сильно отличается от веса благодаря наличию стандартного и надежного способа настройки тестовых данных.
Spring DI помогает сделать тесты краткими и самоописательными, но это не критическая функция.
Ответ 3
Использование Spring и Spring модульного тестирования - лучший способ. С spring вам не требуется два файла persistence.xml, так как ваш persistence.xml ничего не имеет в нем, все указано Spring (все, что мы укажем в нашем persistence.xml, - это имя единицы сохранения), и, таким образом, вы может изменить конфигурацию базы данных и т.д. с помощью spring.
И как отметил топчеф, тестирование на основе транзакций отлично.
Ответ 4
Как уже упоминалось здесь: http://www.devx.com/java/Article/36785/1954,
вы можете удалить следующие строки из проекта .settings/org.eclipse.wst.common.component
, чтобы избежать развертывания тестовых ресурсов в веб-приложении.
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/resources"/>