2009-10-07 2 views
16

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

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(); 

Я отправил вопрос как последующую Is there any way for DBUnit to automatically create tables from a dataset or dtd?

ответ

19

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

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

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

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


Update: 20171115

С тех пор я перешел на использование JUnit rules that start up a real instance of the database server и что-то вроде FlywayDB построить базу данных (и с использованием тех же сценариев в прямом эфире, как в тесте, с приложением, ответственным за строительство база данных). Это значительно медленнее, чем использование предварительно созданной базы данных. Однако, используя хорошо определенные микросервисы (и, следовательно, уменьшая функциональность, требующую тестирования), и будучи очень плотно, на каких тестах получает базу данных, вы можете перенести такие проблемы и получить преимущества локальной базы данных, которая всегда соответствует живым.

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

+0

Я теперь перешли к локальному экземпляру Oracle XE работает в VM. Причина этого в том, что мы можем продолжать развиваться, когда не подключены к внутренней сети. –

+3

Имея базу данных в памяти, я могу запускать модульные тесты в любом месте, без необходимости менять конфигурацию и не запускать сервер БД. В первую очередь они запускаются в разных dev-блоках и на сервере CI. Это огромное преимущество в моей книге. – Spencer

+0

Да, это так. Я лично обнаружил, что он значительно медленнее, но теперь это может измениться. Время, затраченное на запуск локального экземпляра Oracle XE в VM, - это короткая вещь раз в день. –

0

В случае, если вы создадите свои таблицы вверх, как предлагалось here, и по-прежнему получаете исключение NoSuchTableException, то что-то не так с схемой. Перед тем, как теперь обратиться с ума, возился с ним во всевозможных странных и удивительных способов, попробуйте установить параметр схемы для ОБЩЕСТВЕННОГО при создании IDatabaseConnection, например, так:

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

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

4

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

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

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

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

Смежные вопросы