Подтвердить что ты не робот

Как проверить с помощью DBUnit с помощью простых JDBC и HSQLDB, не сталкиваясь с NoSuchTableException?

Я пытаюсь использовать DBUnit с обычными JDBC и HSQLDB и не могу заставить его работать, хотя я использовал DBUnit с Hibernate раньше с большим успехом. Здесь код:

import java.sql.PreparedStatement;
import org.dbunit.IDatabaseTester;
import org.dbunit.JdbcDatabaseTester;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.XmlDataSet;
import org.junit.Test;

public class DummyTest {

    @Test
    public void testDBUnit() throws Exception {
        IDatabaseTester databaseTester = new JdbcDatabaseTester("org.hsqldb.jdbcDriver", "jdbc:hsqldb:mem", "sa", "");
        IDataSet dataSet = new XmlDataSet(getClass().getResourceAsStream("dataset.xml"));
        databaseTester.setDataSet(dataSet);
        databaseTester.onSetup();
        PreparedStatement pst = databaseTester.getConnection().getConnection().prepareStatement("select * from mytable");
    }
}

И это вопрос dataset.xml:

<dataset>
    <table name="mytable">
        <column>itemnumber</column>
        <column>something</column>
        <column>other</column>
        <row>
            <value>1234abcd</value>
            <value>something1</value>
            <value>else1</value>
        </row>
    </table>
</dataset>

Этот тест дает мне исключение NoSuchTableException:

org.dbunit.dataset.NoSuchTableException: mytable
    at org.dbunit.database.DatabaseDataSet.getTableMetaData(DatabaseDataSet.java:282)
    at org.dbunit.operation.DeleteAllOperation.execute(DeleteAllOperation.java:109)
    at org.dbunit.operation.CompositeOperation.execute(CompositeOperation.java:79)
    at org.dbunit.AbstractDatabaseTester.executeOperation(AbstractDatabaseTester.java:190)
    at org.dbunit.AbstractDatabaseTester.onSetup(AbstractDatabaseTester.java:103)
    at DummyTest.testDBUnit(DummyTest.java:18)

Если я удалю строку databaseTester.onSetup(), вместо этого получаю вместо этого SQLException:

java.sql.SQLException: Table not found in statement [select * from mytable]
    at org.hsqldb.jdbc.Util.throwError(Unknown Source)
    at org.hsqldb.jdbc.jdbcPreparedStatement.<init>(Unknown Source)
    at org.hsqldb.jdbc.jdbcConnection.prepareStatement(Unknown Source)
    at DummyTest.testDBUnit(DummyTest.java:19)

Набор данных сам по себе работает, так как я могу получить к нему доступ, как и должно:

ITable table = dataSet.getTable("mytable");
String firstCol = table.getTableMetaData().getColumns()[0];
String tName = table.getTableMetaData().getTableName();

Что мне здесь не хватает?

EDIT. Как указывает @mlk, DBUnit не создает таблицы. Если я вставляю следующие данные перед добавлением набора данных, все идет гладко:

PreparedStatement pp = databaseTester.getConnection().getConnection().prepareStatement(
     "create table mytable ( itemnumber varchar(255) NOT NULL primary key, "
   + " something varchar(255), other varchar(255) )");
pp.executeUpdate();

Я разместил следующий вопрос как Есть ли способ DBUnit для автоматического создания таблиц из набора данных или dtd?

4b9b3361

Ответ 1

dbUnit не создает таблицы. И это не могло быть связано с ограниченной информацией, приведенной в файле XML. Спящий режим, я считаю, может создавать таблицы.

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

Вторая причина - скорость. Я обнаружил, что создание базы данных в памяти заняло гораздо больше времени, чем просто подключение к существующей базе данных.

Третья причина заключалась в том, что срыв не является разрушительным (запуск стирает базу данных). Это означает, что я могу запустить SQL-тест в базе данных, чтобы помочь решить, почему тест терпит неудачу.


Обновление: 20171115

С тех пор я переключился на использование правил JUnit, которые запускают настоящий экземпляр сервера баз данных и что-то вроде FlywayDB для создания базы данных (и с использованием тех же сценариев, что и в тесте, с приложением, ответственным за создание базы данных). Это значительно медленнее, чем использование предварительно созданной базы данных. Однако, используя хорошо определенные микросервисы (и, следовательно, уменьшая функциональность, требующую тестирования) и будучи очень плотно, на каких тестах получает базу данных, вы можете перенести такие проблемы и получить преимущества локальной базы данных, которая всегда соответствует живым.

Это, конечно, означает, что тестовый разрыв всегда разрушительный, но хорошо подобранная точка прерывания решает это.

Ответ 2

... через несколько лет у нас появились лучшие варианты

Spring Загрузка / Spring JDBC может инициализировать базу данных с помощью простого JDBC.

Spring JDBC имеет функцию инициализатора DataSource. Spring Загрузка позволяет по умолчанию и загружает SQL из стандартных местоположений schema.sql и data.sql (в корне пути к классам). Кроме того, Spring Boot будет загрузите файлы schema-${platform}.sql и data-${platform}.sql (если present), где платформа - это значение spring.datasource.platform, например вы можете выбрать его для имени поставщика базы данных (hsqldb, h2, oracle, mysql, postgresql и т.д.).

https://docs.spring.io/spring-boot/docs/current/reference/html/howto-database-initialization.html

Ответ 3

Если вы создадите свои таблицы вверх, например, предлагаемые здесь, и по-прежнему получите исключение NoSuchTableException, то что-то не так с схемой. Прежде чем вы теперь сходите с ума, возитесь с ним всякими странными и замечательными способами, попробуйте установить параметр схемы PUBLIC при создании IDatabaseConnection, например:

IDatabaseConnection databaseConnection = new HsqldbConnection(sqlConnection, "PUBLIC");

Мне потребовался некоторый шаг через код DbUnit с отладчиком, но это, похоже, делает трюк.