Как протестировать 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");
    }
}

и это набор данных.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();

что я пропустила?

редактировать: как указывает @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?

3 ответов


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

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

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

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


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

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

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


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

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

Spring JDBC имеет функцию инициализатора источника данных. Ботинок весны включает он по умолчанию и загружает SQL из стандартных местоположений schema.sql и data.sql (в корне классов). Кроме того весной загрузки загрузите 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


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

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

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