JPA – Как обрезать таблицы между модульными тестами

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

Вопрос

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

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

Спасибо Тео

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

Решение

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

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

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

Самый простой способ сделать это, вероятно, использует метод NareQuery 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();
}

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

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

  1. Идентификаторы отслеживания всех объектов, которые были созданы во время теста
  2. накапливать их в порядке создания
  3. Воспроизвести сущность удаляет для этих объектов в обратном порядке в @After

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

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

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

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

  1. Перепасть БД - сценарий SQL, который бросает все таблицы.
  2. Создайте БД - сценарий SQL, который их воссоздает.
  3. Сценарий XML-скрипта DB, специфичный тестовой единицей DB для заполнения данных.

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

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

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

  1. установить свойство "...база данных.действие"по стоимости"«брось и создай»" в вашей конфигурации модуля персистентности
  2. закройте менеджер сущностей и фабрику менеджеров сущностей после каждого теста

персистентность.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();
}

...

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