【问题标题】:Mocking groovy.sql.Sql.call(_,_,_) method模拟 groovy.sql.Sql.call(_,_,_) 方法
【发布时间】:2016-02-09 18:52:53
【问题描述】:

我正在尝试模拟 groovy.sql.Sql call(query, params[],closure) 类。 下面是我正在尝试的 DatabaseService 类文件中的方法。

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(,,_) 方法以仅跳过数据库逻辑,并将列表返回给 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
}

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

【问题讨论】:

  • 为什么不只是模拟服务方法只返回列表
  • 因为这不会测试关闭是否有效
  • 嗯...我要么伪造数据源,要么提取闭包以便测试

标签: grails groovy mocking spock


【解决方案1】:
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,而应该重写您的服务/dao 层以提高可测试性。使用内存数据库测试 dao,并使用模拟的 dao 测试服务层。

【讨论】:

  • 原始方法抛出 groovy.lang.MissingMethodException: No signature of method: java.util.ArrayList.next() is applicable for argument types: () values: [] 可能的解决方案:get(int ), get(int), set(int, java.lang.Object), set(int, java.lang.Object), wait(), head() 在 (result.next()) {} ) 中的调用getUsers 方法
  • 虽然我知道我可以重写它以使其更具可测试性,但我会推断出模拟方法,但省略闭包应该不是那么困难。此外,我宁愿重用已经构建的方法,也不愿从头开始编写。 :) 也许在 groovy 中有另一种方法,它会从preparedCall返回一个结果集,我不知道
  • 这不是关于 groovy,而是关于模拟 jdbc 驱动程序:这并不容易,而且对测试没有真正的用处
  • 看来我们正在创建的数组,我们做错了。 groovy.lang.MissingPropertyException:没有这样的属性:类的 EMAIL:java.util.ArrayList$Itr
  • 您现在必须模拟一个 ResultSet。你真的应该看看内存数据库中的各种。您可以使用 2 行代码创建连接
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-18
  • 2017-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多