我有两个jUnit测试类,一个用于测试我的ItemService
类,另一个用于测试我的LocationService
类。当我运行ItemService
测试时,它会通过。当我运行LocationService
测试时,它失败了:
引起:java.sql.SQLException:在语句[SELECT COUNT(*)FROM locations]中找不到表 在org.hsqldb.jdbc.Util.throwError(未知来源) 在org.hsqldb.jdbc.jdbcPreparedStatement。(未知来源) 在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
?
编辑思想可能存在区分大小写问题,但即使尝试从LOCATIONS
表中进行SELECT也会失败:
引起:java.sql.SQLException:在语句[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:语句中没有找到表[SELECT COUNT(*)FROM ITEMS]
修改:当我没有使用static
@BeforeClass
/ @AfterClass
方法时(即,当测试找不到时),逐步调试调试器表),我注意到以下控制台输出:
2012年4月10日上午10:22:44 org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory initDatabase 信息:创建嵌入式数据库'myTestDB' 2012年4月10日上午10:22:44 org.springframework.jdbc.datasource.init.ResourceDatabasePopulator executeSqlScript 信息:从类路径资源[test-ddl.sql]执行SQL脚本 2012年4月10日上午10:22:44 org.springframework.jdbc.datasource.init.ResourceDatabasePopulator executeSqlScript 信息:在30毫秒内完成从类路径资源[test-ddl.sql]执行SQL脚本。 2012年4月10日上午10:22:44 org.springframework.jdbc.datasource.init.ResourceDatabasePopulator executeSqlScript 信息:从类路径资源[test-data.sql]执行SQL脚本 2012年4月10日上午10:22:44 org.springframework.jdbc.datasource.init.ResourceDatabasePopulator executeSqlScript 信息:在46毫秒内完成从类路径资源[test-data.sql]执行SQL脚本。 2012年4月10日上午10:22:55 org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory initDatabase 信息:创建嵌入式数据库'myTestDB' 2012年4月10日上午10:23:08 org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory initDatabase 信息:创建嵌入式数据库'myTestDB'
所以看起来它设置数据库并运行我的create-tables和populate-tables
最初的脚本,然后在我重新初始化_db
之后的任何时间,脚本都不会再次运行。因此,后续测试方法不存在这些表。因此,如果我能找到一种方法强制Spring每次重新运行这些脚本,我可以回到使用@Before
和@After
使用实例方法来设置和拆卸方法。
答案 0 :(得分:2)
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脚本,因此每个测试都有表格。
答案 1 :(得分:1)
@BeforeClass
和static
!我更改了我的测试类,以便进行以下设置和拆卸方法:
private static EmbeddedDatabase _db;
private static LocationService _svc;
@BeforeClass
public static void setUp() throws Exception {
_db = new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL)
.setName("myTestDB").build();
assertThat(_db, is(notNullValue()));
_svc = new LocationService();
_svc.setDataSource(_db);
}
@AfterClass
public static void tearDown() throws Exception {
_db.shutdown();
}
现在我的ItemService
和LocationService
测试都在通过,即使是在课堂上进行其他测试也是如此。我之前收到的“声明中未找到的表”错误似乎有点奇怪,以回应之前的每次测试设置与before-all-tests-in-class设置...