JPA - Как обрезать таблицы между юнит-тестами - PullRequest
13 голосов
/ 13 октября 2010

Я хочу очищать базу данных после каждого теста без отката транзакции. Я пробовал DBUnit DatabaseOperation.DELETE_ALL , но он не работает, если удаление нарушает ограничение внешнего ключа. Я знаю, что могу отключить проверки внешнего ключа, но это также отключило бы проверки для тестов (которые я хочу предотвратить).

Я использую JUnit 4, JPA 2.0 (Eclipselink) и базу данных Derby в памяти. Есть идеи?

Спасибо, Тео

Ответы [ 6 ]

18 голосов
/ 22 апреля 2013

Простейшим способом сделать это, вероятно, является использование метода nativeQuery jpa.

@After
public void cleanup() {
    EntityManager em = entityManagerFactory.createEntityManager();
    em.getTransaction().begin();
    em.createNativeQuery("truncate table person").executeUpdate();
    em.createNativeQuery("truncate table preferences").executeUpdate();
    em.getTransaction().commit();
}
4 голосов
/ 20 июля 2011

Простой: перед каждым тестом начинайте новую транзакцию и после теста откатывайте ее обратно Это даст вам ту же базу данных, что и раньше.

Убедитесь, что тесты не создают новые транзакции; вместо этого повторно используйте существующий.

2 голосов
/ 14 октября 2010

Да, проверка внутри транзакции сделает вашу жизнь намного проще, но если транзакция - ваша вещь, то вам нужно реализовать компенсационные транзакции во время очистки (в @After). Это кажется трудоемким, и это может быть, но при правильном подходе вы можете получить набор вспомогательных методов (в тестах), которые компенсируют (очищают) данные, накопленные во время @Before, и тесты (с использованием JPA или прямого JDBC - все, что имеет смысл).

Например, если вы используете JPA и вызываете методы create для сущностей во время тестов, вы можете использовать (используя AOP, если вам нравятся или просто вспомогательные методы тестирования, такие как мы) шаблон для всех тестов:

  1. отслеживание идентификаторов всех сущностей, которые были созданы во время теста
  2. накапливайте их в созданном порядке
  3. Повтор воспроизведения объекта для этих объектов в обратном порядке в @After
1 голос
/ 13 октября 2010

Я немного запутался, так как DBUnit будет переинициализировать базу данных до известного состояния перед каждым тестом.

Они также рекомендуют в качестве рекомендации не очищать или иным образом изменять данные после теста.

Так что, если вы хотите очистить базу данных для следующего теста, я не стал бы беспокоиться.

0 голосов
/ 12 июня 2018

Лучше поздно, чем никогда ... У меня была та же проблема, и я нашел довольно простое решение:

  1. установите для свойства " ... database.action " значение " drop-and-create " в конфигурации единицы хранения
  2. закрывать менеджер сущностей и фабрику менеджеров сущностей после каждого теста

persistence.xml

    <persistence-unit name="Mapping4" transaction-type="RESOURCE_LOCAL" >
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>...</class>
    <class>...</class>

    <properties>
        ...
        <property name="javax.persistence.schema-generation.database.action" value="drop-and-create" />
        ...
    </properties>
</persistence-unit>

юнит-тест:

...
@Before
public void setup() {
    factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
    entityManager = factory.createEntityManager();
}


@After
public void tearDown() {
    entityManager.clear();
    entityManager.close();
    factory.close();
}

...

0 голосов
/ 20 июля 2011

Мои настройки очень похожи: это Derby (встроенный) + OpenJPA 1.2.2 + DBUnit. Вот как я выполняю интеграционные тесты для моей текущей задачи: в каждом методе @Before я запускаю 3 сценария:

  1. Удалить БД & mdash; SQL-скрипт, который удаляет все таблицы.
  2. Создать базу данных & mdash; сценарий SQL, воссоздающий их.
  3. Специальный XML-скрипт модуля БД для заполнения данных.

В моей базе данных всего 12 таблиц, и набор тестовых данных тоже невелик & mdash; около 50 записей. На выполнение каждого сценария уходит около 500 мс, и я поддерживаю их вручную при добавлении или изменении таблиц.

Этот подход, вероятно, не рекомендуется для тестирования больших баз данных, и, возможно, его даже нельзя считать хорошей практикой для маленьких; однако у него есть одно важное преимущество по сравнению с откатом транзакции в методе @After: вы действительно можете обнаружить, что происходит при фиксации (например, сохранение отсоединенных объектов или исключений оптимистической блокировки).

...