刺激 JDBC
Spocking the JDBC
我有一些 Groovy 2.4.x 代码使用了一些 JDBC:
class WidgetPersistor {
@Inject // Gets injected correctly by Guice, don't worry about it!
DataSource dataSource
Fizz getFizzByWidgetName(String name) {
Connection conn
PreparedStatement ps
ResultSet rs
try {
// JDBC code here
} catch(SQLException sqlExc) {
if(conn) {
try {
// NOTE: At the end of the day, I just want to verify
// that, given the 'name' arg to this method, the rollback
// doesn't fire!
conn.rollback()
} catch(SQLException rollBackExc) {
throw rollBackExc
}
}
throw sqlExc
} finally {
if(conn) {
try {
rs.close()
ps.close()
conn.close()
} catch(SQLException closingExc) {
throw closingExc
}
}
}
}
}
我正在尝试编写一个 Spock 测试来执行此 getFizzByWidgetName
方法并验证 conn.rollback()
方法 never 执行(意味着我们从未尝试过回滚)。
这是我的最佳尝试:
def "getFizzByWidgetName succeeds without rollback"() {
given: "data client with db connections"
// Don't worry about how I get this for my test, but its a legit JDBC connection
DataSource ds = provideDataSource()
Connection mockConn = Mock(Connection)
PreparedStatement mockPS = Mock(PreparedStatement)
ResultSet mockRS = Mock(ResultSet)
mockPS.executeQuery() >> mockRS
mockConn.prepareStatement(_) >> mockPS
ds.connection >> mockConn // ??? Its like I want the DataSource half-mocked...
WidgetPersistor client = new WidgetPersistor(mockDS)
when: "we try to query something"
client.getFizzByWidgetName('fizzbuzz')
then: "we dont get any errors"
0 * mockConn.rollback()
}
知道我哪里出错了吗?
如果您使用的是来自真实数据库的数据源,并且您的测试代码是用 Groovy 编写的(看起来是这样),您可以使用元类来测试此类事情:
DataSource ds = provideDataSource()
def connection = ds.connection
connection.metaClass.rollback = { throw new AssertionError("rollback called") }
ds.metaClass.connection = connection
但它不是很漂亮。您可能应该在不使用模拟的情况下调用您的方法,并测试数据库的状态(即数据已提交,未回滚)
我有一些 Groovy 2.4.x 代码使用了一些 JDBC:
class WidgetPersistor {
@Inject // Gets injected correctly by Guice, don't worry about it!
DataSource dataSource
Fizz getFizzByWidgetName(String name) {
Connection conn
PreparedStatement ps
ResultSet rs
try {
// JDBC code here
} catch(SQLException sqlExc) {
if(conn) {
try {
// NOTE: At the end of the day, I just want to verify
// that, given the 'name' arg to this method, the rollback
// doesn't fire!
conn.rollback()
} catch(SQLException rollBackExc) {
throw rollBackExc
}
}
throw sqlExc
} finally {
if(conn) {
try {
rs.close()
ps.close()
conn.close()
} catch(SQLException closingExc) {
throw closingExc
}
}
}
}
}
我正在尝试编写一个 Spock 测试来执行此 getFizzByWidgetName
方法并验证 conn.rollback()
方法 never 执行(意味着我们从未尝试过回滚)。
这是我的最佳尝试:
def "getFizzByWidgetName succeeds without rollback"() {
given: "data client with db connections"
// Don't worry about how I get this for my test, but its a legit JDBC connection
DataSource ds = provideDataSource()
Connection mockConn = Mock(Connection)
PreparedStatement mockPS = Mock(PreparedStatement)
ResultSet mockRS = Mock(ResultSet)
mockPS.executeQuery() >> mockRS
mockConn.prepareStatement(_) >> mockPS
ds.connection >> mockConn // ??? Its like I want the DataSource half-mocked...
WidgetPersistor client = new WidgetPersistor(mockDS)
when: "we try to query something"
client.getFizzByWidgetName('fizzbuzz')
then: "we dont get any errors"
0 * mockConn.rollback()
}
知道我哪里出错了吗?
如果您使用的是来自真实数据库的数据源,并且您的测试代码是用 Groovy 编写的(看起来是这样),您可以使用元类来测试此类事情:
DataSource ds = provideDataSource()
def connection = ds.connection
connection.metaClass.rollback = { throw new AssertionError("rollback called") }
ds.metaClass.connection = connection
但它不是很漂亮。您可能应该在不使用模拟的情况下调用您的方法,并测试数据库的状态(即数据已提交,未回滚)