java – HSQLDB在Spring 3 jUnit测试的语句中找不到表

我有两个jUnit测试类,一个用于测试我的ItemService类,另一个用于测试我的LocationService类.当我运行ItemService测试时,它会通过.当我运行LocationService测试时,它失败了:Caused by: java.sql.SQLException: Table...

我有两个jUnit测试类,一个用于测试我的ItemService类,另一个用于测试我的LocationService类.当我运行ItemService测试时,它会通过.当我运行LocationService测试时,它失败了:

Caused by: java.sql.SQLException: Table not found in statement [SELECT COUNT(*) FROM locations]
at org.hsqldb.jdbc.Util.throwError(Unknown Source)
at org.hsqldb.jdbc.jdbcPreparedStatement.(Unknown Source)
at org.hsqldb.jdbc.jdbcConnection.prepareStatement(Unknown Source)

我有一个模式文件被加载到数据库中,它创建的第一个表是ItemService使用的表.也许我的LocationService测试使用的位置表不会被创建,即使它位于相同的模式文件中?

这是在我的test-context.xml文件中:

<jdbc:embedded-database
    id="myTestDB"
    type="HSQL">
    <jdbc:script
        location="classpath:/test-ddl.sql" />
    <jdbc:script
        location="classpath:/test-data.sql" />
</jdbc:embedded-database>

<bean
    id="dataSourceTest"
    class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property
        name="driverClassName"
        value="org.hsqldb.jdbcDriver" />
    <property
        name="url"
        value="jdbc:hsqldb:mem:myTestDB" />
    <property
        name="username"
        value="sa" />
    <property
        name="password"
        value="" />
</bean>

我不明白为什么一个测试通过没有抛出有关缺少项表的错误,而另一个测试失败,因为数据库中不存在位置.我看到有关使用HSQLDB和Hibernate的其他帖子,但我没有使用Hibernate.这些是我在test-ddl.sql文件中创建的表:

CREATE MEMORY TABLE "ITEMS" (
    "ID" INTEGER NOT NULL IDENTITY,
    "NAME" VARCHAR(50) NOT NULL,
    "LOCATION_ID" INTEGER NOT NULL,
    "ITEM_TYPE_ID" INTEGER NOT NULL
);

CREATE MEMORY TABLE "ITEM_TYPES" (
    "ID" INTEGER NOT NULL IDENTITY,
    "NAME" VARCHAR(50) NOT NULL,
    "ICON_CLASS" VARCHAR(50)
);

CREATE CACHED TABLE "LOCATIONS" (
    "ID" INTEGER NOT NULL IDENTITY,
    "NAME" VARCHAR(50) NOT NULL,
    "PHOTO" LONGVARBINARY,
    "PHOTO_CONTENT_TYPE" VARCHAR(60),
    "PHOTO_WIDTH" INTEGER,
    "PHOTO_HEIGHT" INTEGER
);

我还在表创建语句之后在模式中设置了一些UNIQUE和FOREIGN KEY约束,但肯定会告诉我它是否无法创建.我正在使用HSQLDB 1.8.1.3 JAR.为什么我不能查询位置但我可以查询项目?

编辑:基于this question的思想可能存在区分大小写的问题,但即使尝试从LOCATIONS表中进行SELECT也会失败:

Caused by: java.sql.SQLException: Table not found in statement [SELECT COUNT(*) FROM LOCATIONS]

编辑:我神奇的工作ItemService测试:

@ContextConfiguration("/test-context.xml")
@RunWith(SpringJUnit4ClassRunner.class)
@TransactionConfiguration(transactionManager = "transactionManager")
public class ItemServiceTest {
    private EmbeddedDatabase _db;
    private ItemService _svc;

    @Before
    public void setUp() throws Exception {
        _db = new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL)
            .setName("myTestDB").build();
        assertThat(_db, is(notNullValue()));
        _svc = new ItemService();
        _svc.setDataSource(_db);
    }

    @After
    public void tearDown() throws Exception {
        _db.shutdown();
    }

    @Test
    public void testGetCount() {
        assertThat(_svc.getCount(), is(not(0)));
    }
}

我失败的LocationService测试完全相同,但是使用LocationService而不是ItemService. getCount()方法显示在LocationService和ItemService中:

public int getCount() {
    String sql = "SELECT COUNT(*) FROM " + TABLE_NAME;
    return _jdbcTmpl.queryForInt(sql, (Map<String, Object>)null);
}

TABLE_NAME因ItemService而异:

public static final String TABLE_NAME = "ITEMS";

和LocationService:

public static final String TABLE_NAME = "LOCATIONS";

ItemService和LocationService都具有以下内容:

private NamedParameterJdbcTemplate _jdbcTmpl;

@Resource(name = "dataSource")
public void setDataSource(DataSource dataSource) {
    _jdbcTmpl = new NamedParameterJdbcTemplate(dataSource);
}

编辑:问题的新转折.在我的LocationService测试中,我还有其他一些尚未充实的测试方法,例如:

@Test
public void testFind() {
    fail("Not yet implemented");
}

在我的ItemService测试中,唯一的@Test方法是传递的testGetCount.当我将上面的testFind添加到ItemService测试类时,突然它的testGetCount就像我的LocationService测试类一样失败:

Caused by: java.sql.SQLException: Table not found in statement [SELECT COUNT(*) FROM ITEMS]

编辑:当我没有使用静态@ BeforeClass / @ AfterClass方法时(即,当测试找不到表时)单步执行调试器,我注意到以下控制台输出:

Apr 10, 2012 10:22:44 AM org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory initDatabase
INFO: Creating embedded database ‘myTestDB’
Apr 10, 2012 10:22:44 AM org.springframework.jdbc.datasource.init.ResourceDatabasePopulator executeSqlScript
INFO: Executing SQL script from class path resource [test-ddl.sql]
Apr 10, 2012 10:22:44 AM org.springframework.jdbc.datasource.init.ResourceDatabasePopulator executeSqlScript
INFO: Done executing SQL script from class path resource [test-ddl.sql] in 30 ms.
Apr 10, 2012 10:22:44 AM org.springframework.jdbc.datasource.init.ResourceDatabasePopulator executeSqlScript
INFO: Executing SQL script from class path resource [test-data.sql]
Apr 10, 2012 10:22:44 AM org.springframework.jdbc.datasource.init.ResourceDatabasePopulator executeSqlScript
INFO: Done executing SQL script from class path resource [test-data.sql] in 46 ms.
Apr 10, 2012 10:22:55 AM org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory initDatabase
INFO: Creating embedded database ‘myTestDB’
Apr 10, 2012 10:23:08 AM org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory initDatabase
INFO: Creating embedded database ‘myTestDB’

所以看起来它设置了数据库并运行我的create-tables和populate-tables
最初的脚本,然后在我重新初始化_db之后的任何时候,脚本都不会再次运行.因此,后续测试方法不存在这些表.因此,如果我能找到一种方法强制Spring每次重新运行这些脚本,我可以回到使用@Before和@After使用实例方法来设置我的设置和拆卸方法.

解决方法:

addScript就是答案.我从test-context.xml中删除了初始化脚本,因此我的jdbc:embedded-database标记如下所示:

<jdbc:embedded-database
    id="myTestDB"
    type="HSQL" />

在我的测试类中的setUp()方法中,我将_db初始化更改为:

_db = new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL)
    .setName("myTestDB").addScript("test-ddl.sql")
    .addScript("test-data.sql").build();

我的setUp和tearDown方法仍然是实例方法,分别用@Before和@After注释.使用调试器,我看到每个测试的控制台输出,说我运行了两个初始化SQL脚本,因此每个测试都存在表.

本文标题为:java – HSQLDB在Spring 3 jUnit测试的语句中找不到表

基础教程推荐