首页 > 解决方案 > 如何在 Spock Groovy 的 THEN 阶段中的预期模拟方法调用之后设置变量?

问题描述

我想用Spock Groovy测试我的 Java 服务,该服务有点棘手,因为方法调用会返回一个值,并且还会更改传递给该方法的变量的内容。

因为我想模拟这个方法调用,所以我需要以某种方式告诉 Spock,当方法执行时,返回一个特定的值并更改传递的变量的内容。

像这样的东西:

given: "list with one element"
List<String> list = ["mock"]

when: "executing the service call"
service.execute(list)

then: "external method is called, which updates the passed variable and returns true as success"
1 * external.addOneMoreToList(list) >> true
and: "list is updated successfully"
list.size == 2
list.get(1) == "mock 2"

但我不知道在哪里以及如何通过添加下一个元素来更新列表:“mock 2”。

我知道这个例子没有意义,但我不想写我真正的测试用例,因为它很大,但我需要类似的 ad-hoc-update

标签: javaunit-testingtestinggroovyspock

解决方案


使用闭包而不是简单的值进行交互,如下所示:

1 * external.addOneMoreToList(list) >> { list ->
    list << 'mock 2'
    return true
}

一些惯用的注释:

  • 在这种情况下实际上没有必要这样做return true,因为(假设您的返回类型是boolean)Groovy 会认为非空列表是真实的。清楚一点仍然是个好主意。

  • 与在 JUnit 中一样,期望值先出现,然后是实际值 ( 2 == list.size())。

  • List您可以使用[]:索引到 a中'mock 2' == list[1]

  • 在实际可行的情况下使用随机值(例如您的'mock 2'值)是一个好主意,因为这有助于防止意外通过。您可以在given块中设置变量并在交互中使用它们;我通常使用 commons-lang3 RandomStringUtils

并尝试将您的测试用例缩小到实际可行的程度!Spock 友好的交互模拟使得对可能过于复杂的接口使用测试替身变得不那么痛苦,并且扩展交互可能是一个合理的用例@Stepwise(我已经将它用于具有多步骤场景的 Selenium 测试)。


推荐阅读