Фреймворк модульного тестирования БД? - PullRequest
7 голосов
/ 04 августа 2011

В моем проекте я использовал spring, jpa с PostgreSQL DB, У меня много таблиц в БД, и мне нужно провести модульное тестирование всех из них.

Существует ли какая-либо инфраструктура, которая просто откатывает все транзакции после каждого теста, чтобы каждый тест имел свежие / одинаковые данные БД для тестирования. И таким образом после всех тестовых выполнений данные схемы БД будут такими, какие они есть.

Есть предложения по этому поводу?

У меня есть некоторое представление о DBUnit, но в этом мне нужно писать файлы .xml для всех входных данных для каждого теста и вставлять данные в setup () и удалять / удалять данные в tearDown (), но не мне кажется, лучшая стратегия.

Любое предложение приветствуется. Спасибо.

Ответы [ 4 ]

4 голосов
/ 04 августа 2011

Как указывает @Ryan .... следует обратиться к разделу Тестирование Справочного руководства по пружине .

Некоторые советы по запуску ...

Мыобработал это, используя AbstractTransactionalJUnit4SpringContextTests.

Spring. Например, мы определяем абстрактный суперкласс:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:WebContent/WEB-INF/testconfig/test-web-application-config.xml")
@TransactionConfiguration()
@Transactional
public abstract class OurAbstractTransactionalSpringContextTest extends AbstractTransactionalJUnit4SpringContextTests {
}

А затем отдельные подклассы, которые нуждаются в дополнительном контексте, определяются как:

@ContextConfiguration("classpath:path/to/config/ConfigForTestCase.xml")
public class TestOurFunction extends OurAbstractTransactionalSpringContextTest {
    @Test
    public void testOurMethod() {
    }

}

Обратите внимание, что:

  1. Не всем тестовым классам нужен дополнительный контекст для них, пропустите @ContextConfiguration на конкретном подклассе.
  2. Мы выполняем через ant и используем forkmode="perBatch" атрибут в задании junit.Это обеспечивает выполнение всех тестов с одинаковой конфигурацией контекста (исключает перезагрузку контекста Spring для каждого теста).Вы можете использовать @DirtiesContext, чтобы указать, что контекст должен обновляться после метода / класса.
  3. пометить каждый метод аннотацией @Test.Среда Spring не принимает методы, использующие соглашение public void testXXX() Junit.
3 голосов
/ 04 августа 2011

Существует ли какая-либо структура, которая просто откатывает все транзакции после каждого теста, чтобы каждый тест имел свежие / одинаковые данные БД для тестирования. И таким образом после всех тестовых выполнений данные схемы БД будут такими, как есть.

Из моего другого ответа , опубликованного ранее днем, да, это возможно с помощью DbUnit. (Исходя из ваших правок, вам это не нужно; в следующем разделе моего ответа рассматривается, почему я использую DbUnit, а когда я не буду его использовать).

Следующий фрагмент кода демонстрирует, как выполняется настройка каждого теста:

@Before
public void setUp() throws Exception
{
    logger.info("Performing the setup of test {}", testName.getMethodName());
    IDatabaseConnection connection = null;
    try
    {
        connection = getConnection();
        IDataSet dataSet = getDataSet();
        //The following line cleans up all DbUnit recognized tables and inserts and test data before every test.
        DatabaseOperation.CLEAN_INSERT.execute(connection, dataSet);
    }
    finally
    {
        // Closes the connection as the persistence layer gets it's connection from elsewhere
        connection.close();
    }
}

private IDatabaseConnection getConnection() throws Exception
{
    @SuppressWarnings({ "rawtypes", "unused" })
    Class driverClass = Class.forName("org.apache.derby.jdbc.ClientDriver");
    Connection jdbcConnection = DriverManager.getConnection(jdbcURL, "XXX",
            "YYY");
    IDatabaseConnection databaseConnection = new DatabaseConnection(jdbcConnection);
    return databaseConnection;
}

private IDataSet getDataSet() throws Exception
{
    ClassLoader classLoader = this.getClass().getClassLoader();
    return new FlatXmlDataSetBuilder().build(classLoader.getResourceAsStream("database-test-setup.xml"));
}

Файл database-test-setup.xml содержит данные, которые будут вставляться в базу данных для каждого теста. Использование DatabaseOperation.CLEAN_INSERT в методе setup гарантирует, что все таблицы, указанные в файле, будут очищены (путем удаления всех строк) с последующей вставкой указанных данных в файл тестовых данных.

Как избежать DbUnit

Я использую описанный выше подход специально для очистки последовательностей перед началом каждого теста, так как приложение использует провайдера JPA, который обновляет последовательности в отдельной транзакции. Если ваше приложение не делает ничего подобного, то вы можете позволить себе просто запустить транзакцию в вашем методе setup() и выполнить откат после завершения проверки. Если бы мое приложение не использовало последовательности (и если бы я не хотел сбрасывать их), то моя процедура установки была бы такой простой, как:

@Before
public void setUp() throws Exception
{
    logger.info("Performing the setup of test {}", testName.getMethodName());
    // emf is created in the @BeforeClass annotated method
    em = emf.createEntityManager();
    // Starts the transaction before every test
    em.getTransaction.begin();
}

@After
public void tearDown() throws Exception
{
    logger.info("Performing the teardown of test {}", testName.getMethodName());
    if (em != null)
    {
        // Rolls back the transaction after every test
        em.getTransaction().rollback();
        em.close();
    }
}

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

2 голосов
/ 04 августа 2011

Тестовая среда Spring делает именно это для вас.

0 голосов
/ 04 августа 2011

Я бы справился с этим следующим образом.

Когда проект находится в тестовом режиме. Я использовал данные начальной загрузки, чтобы проверить, используя dbdeploy Исправлены данные, которые вы можете утверждать. и используйте dao непосредственно для тестирования уровня DAO и DB вашего приложения.

Надеюсь, это поможет

Обновление

например, в вашей системе есть сущность с именем Person, теперь вы можете проверить это с помощью базовых операций CRUD.

  • Запуск сценариев начальной загрузки данных для загрузки данных
  • получить всех людей из БД и заявить об этом. как бы мудрее увидеть все CRUD

для отката транзакции вы можете пометить

@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)

, поэтому он будет выполнять откат базы данных

...