【问题标题】:Mocking Jdbc interfaces in spock在 spock 中模拟 Jdbc 接口
【发布时间】:2017-07-11 09:45:05
【问题描述】:

我正在开发一个小型 framework 来包装名为 spwrap 的数据库存储过程调用

Here's the code:

@ConfineMetaClassChanges([CallableStatement])
def "Result of output parameter getInt throws SQLException" (){

    given:
        def sqlExceptionMsg = "exception happend while tring to call getInt"
        CallableStatement.metaClass.getObject = { int parameterIndex -> throw new SQLException(sqlExceptionMsg)}

    when:
        def custId = customerDao.createCustomer("Abdullah", "Mohammad")

    then:
        def e = thrown(CallException)
        e.cause == SQLException
        e.cause.message == sqlExceptionMsg
}

createCustomer 方法没有返回对CallableStatement 的引用,但是在后台调用了CallableStatement.getObject(int),我想测试抛出SQLException 的情况。

我正在尝试覆盖 CallableStatement.getObject(int) 类上的 bahvaiour(因为我必须引用框架使用的对象 - 至少在这种情况下)

上述测试失败,因为CallableStatement.getObject(int) 似乎没有被更改。但是,当我使用<< 时,它会抱怨(而且应该)。如何做到这一点?

更新

使用GroovyMock 没有帮助:

// test fails!
def "Calling interface methods calling JDBC Driver methods" (){
    given:
        CustomerDAO customerDAO2 = new DAO.Builder("jdbc:hsqldb:mem:customers", "sa", "").build().create(CustomerDAO);
        def callableStatement = GroovyMock(JDBCCallableStatement, global: true)
    when:
        customerDAO2.createCustomer("Abdullah", "Mohammad")
    then:
        1 * callableStatement.getObject(_ as Integer)
}

我可以使用其他 Mocking 框架实现这一点吗?

【问题讨论】:

  • 由于我对 groovy 元类并不完全熟悉,所以我有一个问题:改变接口的元类会影响该接口的所有实现吗?因为如果不是(我希望如此,鉴于 Java 代理约束),那么这个问题中的代码对CallableStatement 的实际 jdbc 驱动程序实现没有任何作用。
  • 你有什么特别的理由不使用普通的 mock 或 stub 而是使用元类吗?
  • 不,但我认为模拟适用于类的特定实例,但这不是我的情况。

标签: java jdbc mockito spock powermock


【解决方案1】:

根据我的经验,Spock 在模拟静态/最终 Java 代码方面并不是很强大。我采取的解决方法之一是将任何此类方法调用放在他们自己的方法中,Spock 应该没有问题挂钩。

public class MyClass {
    //... stuff ...

    protected Object retrieveObject(int) throws SQLException {
        return CallableStatement.getObject(int)
    }
}

public class MyClassTest extends Specification {
def "Test example for wrapping unmockable method" (){
    given:
        MyClass example = new MyClass();
    when:
        example.callMethod("Parameters")
    then:
        1 * example.retrieveObject(_) >> { throw new SQLException(sqlExceptionMsg) }
}
}

【讨论】:

    猜你喜欢
    • 2018-02-08
    • 1970-01-01
    • 2021-12-05
    • 1970-01-01
    • 2015-08-03
    • 1970-01-01
    • 2022-06-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多