9

我知道这里有关于 dbunit 的讨论。我已经阅读了其中的大部分内容,但我似乎无法找到解决问题的方法。

我已经设置了hibernate和spring。我正在做 TDD,所以我必须在编写代码之前连接一个适当的 DAO 测试框架。我想到了 Dbunit,我开始设置它。这是 ma testdataset.xml

    <?xml version='1.0' encoding='UTF-8'?>
    <dataset>
        <table name="status">
            <column>statusId</column>
            <column>status</column>
            <row>
                <value>0</value>
                <value>Available</value>
            </row>
        </table>
        <table name="user">
            <column>userId</column>
            <column>firstName</column>
            <column>lastName</column>
            <column>username</column>
            <column>password</column>
            <column>email</column>
            <row>
                <value>0</value>
                <value>system</value>
                <value>admin</value>
                <value>admin</value>
                <value>admin</value>
                <value>admin@ccbs.com</value>
            </row>
        </table>
        <table name="reservation">
            <column>reservationId</column>
            <column>userId</column>
            <column>reservationDate</column>
            <column>startDate</column>
            <column>endDate</column>
            <column>statusId</column>
            <row>
                <value>0</value>
                <value>0</value>
                <value>2011-02-20 12:46:00.0</value>
                <value>2011-03-01 12:00:00.0</value>
                <value>2011-04-01 12:00:00.0</value>
                <value>0</value>
            </row>
        </table>
    </dataset>

一切似乎都很好,直到我尝试使用加载数据集的基类来连接一些代码。这是我的代码:

@Transactional
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:test-applicationContext.xml" })
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public class BaseContextSensitiveTest {

    @BeforeClass
public static void setUpDatabase() throws Exception {
    URL file = getInitalDatasetURL();
    testDataset = createDataset(file);
}

   @Before
public void init() throws Exception {
    log.info("Initializing Data Set");
    connection = createDBUnitConnection();

    DatabaseOperation.CLEAN_INSERT.execute(connection, testDataset);
}

private static URL getInitalDatasetURL() throws FileNotFoundException {
    URL file = ClassLoader.getSystemResource(TEST_DATASET_LOCATION);
    if (file == null) {
        throw new FileNotFoundException("Unable to find '"
                + TEST_DATASET_LOCATION + "' in the classpath");
    }
    return file;
}

private static IDataSet createDataset(URL file) throws IOException,
        DataSetException {

    return new XmlDataSet(file.openStream());
}

private IDatabaseConnection createDBUnitConnection()
        throws DatabaseUnitException, SQLException {

    Connection connection = getConnection();
    IDatabaseConnection dbUnitConn = new DatabaseConnection(connection);

    // use the hsql datatypefactory so that boolean properties work
    // correctly
    DatabaseConfig config = dbUnitConn.getConfig();
    config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY,
            new HsqldbDataTypeFactory());

    return dbUnitConn;
}

一旦它命中DatabaseOperation.CLEAN_INSERT.execute(connection, testDataset);它就会抛出以下异常:

org.dbunit.dataset.NoSuchTableException: Did not find table 'USER' in schema 'null'
at org.dbunit.database.DatabaseTableMetaData.<init>(DatabaseTableMetaData.java:142)
at org.dbunit.database.DatabaseDataSet.getTableMetaData(DatabaseDataSet.java:290)
at org.dbunit.operation.DeleteAllOperation.execute(DeleteAllOperation.java:109)
at org.dbunit.operation.CompositeOperation.execute(CompositeOperation.java:79)
at com.cottage.test.BaseContextSensitiveTest.init(BaseContextSensitiveTest.java:64)

我已经准备好所有休眠映射文件,并且数据库已经设置为没有数据。有趣的事情(或恼人的事情,取决于你如何看待它)是,如果我更改数据集中表的顺序,missingtableexception 会抱怨另一个表......用户、预订或状态。

关于我可能做错了什么的任何建议?

4

7 回答 7

13

我也遇到了同样的错误,上面接受的修复并没有解决我的问题。但是我能够找到解决方案。

我的设置包括 DBUnit(2.4)、EclipseLink(2.1) 作为我的 JPA 提供程序,以及 Postgres 作为我的后端数据库。此外,在我的场景中,我没有为每次测试运行删除和重新创建表。我的测试数据已经存在。我知道不好的做法,但这更像是一个测试/原型设计场景。下面的代码说明了用于解决我的问题的 DBUnit 配置。

54    // ctx represents a spring context
55    DataSource ds = (DataSource)ctx.getBean("myDatasourceBean");
56    Connection conn = DataSourceUtils.getConnection(ds);
57    IDatabaseConnection dbUnitConn = new DatabaseConnection(conn, "public");
58    DatabaseConfig dbCfg = dbUnitConn.getConfig();
59    dbCfg.setFeature(DatabaseConfig.FEATURE_CASE_SENSITIVE_TABLE_NAMES, Boolean.TRUE);
60    IDataSet dataSet = new FlatXmlDataSet(ClassLoader.getSYstemResourceAsStream("mydbunitdata.xml"));
61    DatabaseOperation.REFRESH.execute(dbUnitConn, dataSet);

上面代码中的两件事解决了我的问题。首先,我需要定义 DBUnit 应该使用的模式。这是在上面的第 57 行完成的。设置新的 DatabaseConnection 时,如果 schema("public") 不为 null,则应传入。

其次,我需要 DBUnit 对数据库表名区分大小写。在我的 DBUnit xml 文件(“mydbunitdata.xml”)中,表名都是小写的,就像它们在数据库中一样。但是,如果您不告诉 DBUnit 使用区分大小写的表名,它会查找 Postgres 不喜欢的大写表名。因此,我需要在 DBUnit 中设置区分大小写的功能,这是在第 59 行完成的。

于 2011-09-23T13:57:48.730 回答
10

删除 dataset.xml 文件中的第一行

<!DOCTYPE dataset>

并用这个替换它

<?xml version='1.0' encoding='UTF-8'?>

否则 DBUnit 会尝试从 DTD 文件加载 db 表模式,如果没有提供 DTD,它将永远不会在任何表上匹配。使用纯 xml 标头将导致 DBUnit 跳过此 DTD - 表检查,该检查会引发您看到的错误。

您还必须做 Grzegorz 所做的事情,并让 hibernate 通过包括

<property name="hibernate.hbm2ddl.auto" value="create-drop"/>

或者

configuration.setProperty(Environment.HBM2DDL_AUTO, "create-drop");

于 2011-05-06T17:43:55.140 回答
8

DBUnit 不会为您创建数据库表,因为它从数据集 xml 中获得的信息有限,无法创建预期的数据库模式。

当与 hibernate 一起使用时,它需要为每个 pojo 提供适当的 hbm 映射文件(您试图映射到内存中的测试数据库表),最终在测试中使用。如果没有映射文件,您将获得org.dbunit.dataset.NoSuchTableException: Did not find table 'xxx' in schema 'yyy'.

此外,还需要一个有效的 hibernate.cfg.xml,并使用所有 hibernate 映射文件正确配置。

hibernate.hbm2ddl.auto=create-drop您可以通过在属性文件中设置此属性来将数据库创建委托给休眠。

错误消息有点误导。可能应该包含更多关于缺少休眠映射文件的信息——但这是 DBunit wiki 上的讨论。

于 2011-02-21T20:32:23.930 回答
3

您是否在数据库中创建了数据库表?

dbunit不会为你做,因为它不知道预期的数据库结构。但是,您可以要求 Hibernat 执行此操作。使用hbm2ddl标志,例如:

 <property name="hibernate.hbm2ddl.auto" value="create-drop"/>

我找不到标志的主要文档,但如果你搜索它,你会得到很多结果,包括。http://docs.jboss.org/ejb3/docs/reference/build/reference/en/html/entityconfig.html

于 2011-02-21T12:56:14.113 回答
1

你可能对此感兴趣。我也发现了这个错误,通过将 hibernate.cfg.xml 中的表从“消息”重命名为“消息”,它能够找到架构。

让我知道这是否也适合您。

于 2011-07-12T11:27:57.497 回答
1

我遇到了同样的错误,并且在 hibernate.cfg.xml 中配置了我的实体,并且我正在使用 hbm2ddl 生成表,所以我搜索并发现我的实体映射包含一个名为“POSITION”的字段,这是一个保留术语. 当我将其更改为“POS”时,表格已正确生成。

您可以通过调试 resultSet 迭代来检查您的表是否正在生成

org.dbunit.database.DatabaseDataSet.initialize()。

于 2014-10-03T12:23:41.190 回答
0

DbUnit 类从数据库中获取默认架构,如果您要使用的架构不是默认架构,则需要在 .xml 文件中设置所需架构并启用其他架构的识别选项,请参见下面的解决方案。我创造了它。

Example.xml - 多个架构

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
    <SCHEMA1.NAME_TABLE id="5" userName="1" />
    <SCHEMA2.NAME_TABLE id="2" roleName="1" />
<dataset>


<?xml version='1.0' encoding='UTF-8'?>
<dataset>
    <PEOPLE.USER id="5" userName="1" />
    <FUNCTIONS.ROLE id="2" roleName="1" />
<dataset>

测试班

    @Before
    public void initialize() throws Exception{
        //Insert data into database
        DatabaseOperation.CLEAN_INSERT.execute(getConnection(), getDataSet());
    }

    @After
    public void cleanup() throws Exception{
     //Clean up the database
      DatabaseOperation.DELETE_ALL.execute(getConnection(), getDataSet());
      System.out.println("DELETADO COM SUCESSO!");

    }

    private IDatabaseConnection getConnection() throws Exception{
            // Get the database connection
            Connection con = dataSource.getConnection();
            DatabaseMetaData  databaseMetaData = con.getMetaData();
            DatabaseConnection connection = new DatabaseConnection(con,databaseMetaData.getUserName().toUpperCase());
            //Allow multiple schemas to be used
            connection.getConfig().setFeature(DatabaseConfig.FEATURE_QUALIFIED_TABLE_NAMES, true);
            return connection;    
    }

    private IDataSet getDataSet() throws Exception{
        //Get file to insert
        File file = new File("src/test/resources/Example.xml");
        return new FlatXmlDataSet(file);
}
于 2019-07-24T17:39:34.040 回答