模拟 groovy.sql.Sql.call(_,_,_) 方法

Mocking groovy.sql.Sql.call(_,_,_) method

我正在尝试模拟 groovy.sql.Sql 调用(查询、参数 []、闭包)class。 下面是一个 DatabaseService class 文件中的方法,我正在尝试这样做。

public void getUsers(List<User> developerList, Sql sql) {
    sql.call("{? = call GETUSERS()}", [Sql.resultSet(OracleTypes.CURSOR)]) { result ->
        while (result.next()) {
            User user = new User()
            user .email = result.EMAIL
            user .lastName = result.LASTNAME
        }
    }
}

我的模拟确实完成了任务,但是,我不想执行模拟闭包。我想模拟 .call(,,_) 方法只跳过数据库逻辑,并且 return 将列表返回到 getUsers() 方法中的闭包。我希望闭包在 getUsers() 方法中执行,而不是模拟方法。

下面是我用 SPOCK 写的模型。

void "test getUsers(list,sql) some results"() {
    DataSource mockedSource = Mock(DataSource)
    Sql mockedSql = Mock(Sql)
    DatabaseService databaseService = new DatabaseService()
    databaseService.dataSource = mockedSource
    List<User> userList= new ArrayList<>();

    when:
    databaseService.getUsers(userList, mockedSql)

    then:
    1 * mockedSql.call(_, _, _) >> { return [[EMAIL: "A", LASTNAME: "B"]] }
    userList.size() == 1
}

正如想象的那样,这个模型覆盖了原来的方法闭包,我的列表从未被填充。我当然不想重写我的class来使用Java,我也不能改变执行的存储过程。

try :
int resultSetIdx = 0
def resutSet = Mock(ResultSet)
  ...
then:
  1 * mockedSql.call(_, _, _) >> { args -> args[2].call(resultSet) }
  2 * mockedResultset.next() >> { ++resultSetIdx > 1 ? false: true}
  1 * mockedResultset.getString("EMAIL") >> "A"

在 getUsers 方法 () 中更改

user.lastName = result.LASTNAME
user.email = result.EMAIL

user.lastName = result.getString("LASTNAME")
user.email = result.getString("EMAIL")

但是,您不应模拟 Sql,而应重写 service/dao 层以使其更易于测试。使用内存数据库测试 Dao,使用模拟 Dao 测试服务层。