16

プレーンな JDBC と HSQLDB で DBUnit を使用しようとしていますが、以前に Hibernate で DBUnit を使用して大きな成功を収めましたが、うまく動作しません。コードは次のとおりです。

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

ここで何が欠けていますか?

編集: @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 からテーブルを自動的に作成する方法はありますか?というフォローアップの質問を投稿しました。

4

3 に答える 3

19

dbUnit はテーブルを作成しません。また、XML ファイルで指定された限られた情報ではできませんでした。Hibernate でテーブルを作成できると思います。

これが、私がメモリ内データベースの使用をやめ、代わりに DBA に各開発者に独自のデータベースを提供するよう依頼した理由の 1 つです。その後、すべての開発者は、後でライブで実行される同じスクリプトを使用して、データベースを最新の状態に保ちます。これにより、わずかなオーバーヘッドが追加されます (すべての開発者がデータベースを最新の状態に保つ必要があります) が、実行ごとにデータベースを構築する必要がなく、テストで実行されたクエリがライブで動作することを確認できます。

2 つ目の理由は速度でした。インメモリデータベースの作成は、既存のデータベースに単に接続するよりもはるかに時間がかかることがわかりました。

3 つ目の理由は、ティア ダウンが非破壊的であることです (起動するとデータベースが消去されます)。これは、データベースでテスト対象の SQL を実行して、テストが失敗する理由を解明できることを意味します。


更新:20171115

それ以来 、データベース サーバーの実際のインスタンスを起動する JUnit ルールと、FlywayDBのようなものを使用してデータベースを構築する方法に切り替えました (そして、データベースの構築を担当するアプリケーションで、テストと同じスクリプトをライブで使用します)。事前に構築されたデータベースを使用するよりも大幅に遅くなります。ただし、明確に定義されたマイクロサービスを使用して (テストが必要な機能を減らして)、どのテストがデータベースを取得するかを非常に厳しくすることで、そのような問題を移行し、常にライブと一致するローカル データベースの利点を得ることができます。

残念ながら、テストの破棄は常に破壊的であることを意味しますが、適切に配置されたブレークポイントはそれを解決します。

于 2009-10-07T11:54:28.187 に答える
4

...数年後の今、より良い選択肢があります

Spring Boot/Spring JDBC は、プレーンな JDBC でデータベースを初期化できます。

Spring JDBC には DataSource 初期化機能があります。Spring Boot はデフォルトでこれを有効にし、標準の場所schema.sqldata.sql(クラスパスのルート) から SQL をロードします。さらに、Spring Boot はschema-${platform}.sqlおよびdata-${platform}.sqlファイル (存在する場合) をロードします。ここで platform は の値ですspring.datasource.platform。たとえば、データベースのベンダー名 (hsqldb、h2、oracle、mysql、postgresql など) に設定することを選択できます。

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

于 2016-05-03T11:30:27.217 に答える
0

ここで提案されているように事前にテーブルを作成しても NoSuchTableException が発生する場合は、スキーマに問題があります。クレイジーになる前に、あらゆる種類の奇妙で素晴らしい方法でそれをいじります。次のように、を作成するときにschema パラメータをPUBLICに設定してみてください。IDatabaseConnection

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

デバッガーで DbUnit コードをステップ実行するのに少し時間がかかりましたが、これでうまくいくようです。

于 2010-09-20T15:04:37.330 に答える