Как протестировать 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 с отладчиком, но это, похоже, делает трюк.