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  

Но это не очень красиво. Вероятно, вам следует вызывать ваш метод без использования макетов и проверять состояние базы данных (т. Е. Данные были зафиксированы, а не откатаны)

Другие вопросы по тегам