Spocking 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
}
}
}
}
}
Я пытаюсь написать тест Спока, который выполнит это getFizzByWidgetName
метод и убедитесь, что conn.rollback()
метод никогда не выполнялся (это означает, что мы никогда не пытались выполнить откат).
Вот моя лучшая попытка:
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()
}
Любые идеи, где я иду наперекосяк?
1 ответ
Решение
Если вы используете DataSource из реальной базы данных, а тестируемый код написан на Groovy (что выглядит так), вы можете использовать метакласс для проверки такого рода вещей:
DataSource ds = provideDataSource()
def connection = ds.connection
connection.metaClass.rollback = { throw new AssertionError("rollback called") }
ds.metaClass.connection = connection
Но это не очень красиво. Вероятно, вам следует вызывать ваш метод без использования макетов и проверять состояние базы данных (т. Е. Данные были зафиксированы, а не откатаны)