如何在 Spock Groovy 的 THEN 阶段中预期的模拟方法调用后设置变量?

How to set variables after an expected mock method call in THEN stage in Spock Groovy?

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

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

像这样:

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

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

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

一些惯用的注释:

  • 在这种情况下实际上不需要 return true,因为(假设您的 return 类型是 boolean)Groovy 会考虑非-空列表真实。说清楚还是不错的。

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

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

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

并尝试在任何可行的范围内精简您的测试用例! Spock 友好的交互模拟使得对可能过于复杂的接口使用测试替身变得不那么痛苦,并且扩展交互可以是 @Stepwise 的合理用例(我已经将它用于具有多步场景的 Selenium 测试).