使用“真实的”数据库进行单元测试的问题是测试的设置,删除和隔离。您不需要启动一个全新的MySQL数据库并仅为一个单元测试创建表和数据。与此有关的问题与数据库的外部性质有关,并且测试数据库已关闭,单元测试失败。确保您具有用于测试的唯一数据库也存在问题。它们可以克服,但是有一个简单的答案。
模拟数据库是一种选择,但是它不会测试实际运行的查询。当您要确保来自DAO的数据正确通过系统时,它可以用作更简单的解决方案。但是,为了测试DAO本身,您需要在DAO背后提供一些数据,并且查询可以正确运行。
首先要做的是使用内存数据库。 HyperSQL是一个极好的选择,因为它具有模拟另一个数据库的方言的能力-从而使数据库之间的细微差别保持不变(数据类型,功能等)。hsqldb还具有一些不错的单元测试功能。
db.url=jdbc:hsqldb:file:src/test/resources/testData;shutdown=true;
这将从数据库加载数据库的状态(表,初始数据)。 testData
文件中。 shutdown=true
最后一个连接关闭时,它将自动关闭数据库。
使用依赖注入,让单元测试选择一个与生产(或测试或本地)构建使用的数据库不同的数据库。
然后,您的DAO使用注入的数据库,您可以针对该数据库启动测试。
然后,单元测试将类似于(为简洁起见,不包含大量无聊的内容):
@Before
public void setUpDB() {
DBConnection connection = new DBConnection();
try {
conn = connection.getDBConnection();
insert = conn.prepareStatement("INSERT INTO data (txt, ts, active) VALUES (?, ?, ?)");
} catch (SQLException e) {
e.printStackTrace();
fail("Error instantiating database table: " + e.getMessage());
}
}
@After
public void tearDown() {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
private void addData(String txt, Timestamp ts, boolean active) throws Exception {
insert.setString(1, txt);
insert.setTimestamp(2, ts);
insert.setBoolean(3, active);
insert.execute();
}
@Test
public void testGetData() throws Exception {
// load data
Calendar time = Calendar.getInstance();
long now = time.getTimeInMillis();
long then1h = now - (60 * 60 * 1000); // one hour ago
long then2m = now - (60 * 1000 * 2); // two minutes ago
addData("active_foo", new Timestamp(then1h), true); // active but old
addData("inactive_bar", new Timestamp(then1h), false); // inactive and old
addData("active_quz", new Timestamp(then2m), true); // active and new
addData("inactive_baz", new Timestamp(then2m), false); // inactive and new
DataAccess dao = new DataAccess();
int count = 0;
for (Data data : dao.getData()) {
count++;
assertTrue(data.getTxt().startsWith("active"));
}
assertEquals("got back " + count + " rows instead of 1", count, 1);
}
因此,您有一个调用DAO的单元测试,并且正在使用在测试过程中一直存在的动态数据库中设置的数据。您不必担心外部资源或运行前数据库的状态,也不必担心会恢复到已知状态(嗯,“已知状态”是“不存在”,这很容易恢复)。
在设置数据库,创建表和加载数据时,DBUnit可以使我所描述的过程更加简单。如果由于某种原因需要使用实际数据库,那么到目前为止,这是更好的工具。
上面的代码是我为GitHub上的概念验证TestingWithHsqldb而编写的Maven项目的一部分