我正在使用一个小框架来包装数据库存储的过程调用,名为 spwrap
这是代码:
@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)
}
我可以使用其他模仿框架来实现此目标?
在我的经验中,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) }
}
}