我有两个 jUnit 测试类,一个用于测试我的ItemService
类,另一个用于测试我的LocationService
类。当我运行ItemService
测试时,它通过了。当我运行LocationService
测试时,它失败了:
原因:java.sql.SQLException:在 org.hsqldb.jdbc.Util.throwError(Unknown Source) at org.hsqldb.jdbc.jdbcPreparedStatement.(Unknown Source) 的语句 [SELECT COUNT(*) FROM locations] 中找不到表在 org.hsqldb.jdbc.jdbcConnection.prepareStatement(未知来源)
我有一个模式文件被加载到数据库中,它创建的第一个表就是ItemService
使用的表。也许locations
我的测试使用的表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>
我不明白为什么一个测试通过而没有关于items
表丢失的错误,而另一个测试失败,因为locations
数据库中不存在。我看到其他有关使用 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。为什么我不能查询locations
,但我可以查询items
?
编辑:基于this question的想法可能存在区分大小写的问题,但即使尝试从LOCATIONS
表中选择也会失败:
原因: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
测试类中一样失败:
原因:java.sql.SQLException: Table not found in statement [SELECT COUNT(*) FROM ITEMS]
编辑:当我不使用static
@BeforeClass
/@AfterClass
方法时(即,当测试找不到表时)逐步使用调试器,我注意到以下控制台输出:
2012 年 4 月 10 日上午 10:22:44 org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory initDatabase INFO:创建嵌入式数据库“myTestDB” 2012 年 4 月 10 日上午 10:22:44 org.springframework.jdbc.datasource.init。 ResourceDatabasePopulator executeSqlScript INFO:从类路径资源执行 SQL 脚本 [test-ddl.sql] Apr 10, 2012 10:22:44 AM org.springframework.jdbc.datasource.init.ResourceDatabasePopulator executeSqlScript INFO:完成从类路径资源执行 SQL 脚本[test-ddl.sql] 在 30 毫秒内。2012 年 4 月 10 日上午 10:22:44 org.springframework.jdbc.datasource.init.ResourceDatabasePopulator executeSqlScript 信息:从类路径资源 [test-data.sql] 执行 SQL 脚本 2012 年 4 月 10 日上午 10:22:44 springframework.jdbc.datasource.init.ResourceDatabasePopulator 执行SqlScript 信息:在 46 毫秒内完成从类路径资源 [test-data.sql] 执行 SQL 脚本。2012 年 4 月 10 日上午 10:22:55 org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory initDatabase INFO:创建嵌入式数据库“myTestDB” 2012 年 4 月 10 日上午 10:23:08 org.springframework.jdbc.datasource.embedded。 EmbeddedDatabaseFactory initDatabase INFO:创建嵌入式数据库“myTestDB”
所以看起来它设置了数据库并最初运行我的 create-tables 和 populate-tables 脚本,然后在我重新初始化之后的任何时间_db
,脚本不会再次运行。因此,对于后续测试方法,这些表不存在。因此,如果我能找到一种方法来强制 Spring 每次都重新运行这些脚本,我就可以重新使用实例方法来设置和拆卸方法@Before
。@After