我正在尝试将 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();

我在这里缺少什么?

编辑: :正如 @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 创建表吗?

有帮助吗?

解决方案

dbUnit 不创建表。由于 XML 文件中给出的信息有限,也无法做到这一点。我相信 Hibernate 可以创建表。

这是我停止使用内存数据库并让 DBA 为每个开发人员提供自己的数据库的原因之一。然后,每个开发人员使用随后实时运行的相同脚本来保持数据库最新。这会增加一点开销(所有开发人员都需要保持数据库最新),但这意味着您无需为每次运行构建数据库而烦恼,并且可以确保查询在实时测试工作中运行。

第二个原因是速度。我发现创建内存数据库比简单地连接到现有数据库花费的时间要长得多。

第三个原因是拆卸是非破坏性的(启动会擦除数据库)。这意味着我可以在数据库上运行测试中的 SQL,以帮助找出测试失败的原因。


更新: 20171115

从那以后我改用 启动数据库服务器真实实例的 JUnit 规则 和类似的东西 Flyway数据库 构建数据库(并使用与测试中相同的脚本,应用程序负责构建数据库)。它比使用预构建的数据库要慢得多。然而,使用定义良好的微服务(从而减少需要测试的功能)并且非常严格地控制哪些测试获取数据库,您可以迁移此类问题并获得始终匹配实时的本地数据库的好处。

可惜的是,这确实意味着测试拆卸总是具有破坏性的,但是一个适当的断点可以解决这个问题。

其他提示

...几年后,我们有更好的选择

Spring Boot/ Spring JDBC可以使用普通JDBC初始化数据库。

Spring JDBC具有数据源初始化器功能。 Spring Boot默认可以启用它,并从标准位置加载SQL schema.sqldata.sql (在classPath的根部)。另外,春季靴将加载 schema-${platform}.sqldata-${platform}.sql 文件(如果存在),其中平台是 spring.datasource.platform,例如,您可以选择将其设置为数据库的供应商名称(HSQLDB,H2,Oracle,MySQL,PostgreSQL等)。

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

如果您确实会像建议的那样预先创建桌子 这里 并且仍然获得了鼻table Exception,然后该模式出现了问题。在您现在变得疯狂之前,以各种怪异而奇妙的方式摆弄它,请尝试将架构参数设置为 上市 当您创建 IDatabaseConnection, ,像这样:

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

我花了一些时间逐步介绍了调试器,但这似乎可以解决问题。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top