Spock - 交互测试后测试失败

Spock - test fails after interaction testing

此测试仅在测试条件时有效。当与交互测试混合时,它失败了。

class Test extends Specification {

   class Inner {
      public String greet() {
         return "hello"
      }
   }

   def "simple test"() {

      given:
         def inner = Mock(Inner)
         inner.greet() >> { "hi" }
      when:
         def msg = inner.greet()
      then:
         1 * inner.greet() // Below will pass when this line commented out.
         msg == "hi"
   }
}

移除交互测试后测试将通过。

Condition not satisfied:

msg == "hi"
|   |
|   false
null

应该是:

@Grab('org.spockframework:spock-core:0.7-groovy-2.0')
@Grab('cglib:cglib-nodep:3.1')

import spock.lang.*

class Test extends Specification {

    class Inner {
        public String greet() {
            return "hello"
        }
    }

    def "simple test"() {
        given:
            def inner = Mock(Inner)
        when:
            def msg = inner.greet()
        then:
            1 * inner.greet() >> "hi"
            msg == "hi"
    }
}

让我们谈谈正在发生的事情。 (或者,如果您不想阅读,请阅读“Scope of Interactions”部分。)

发生的事情是范围界定问题。您可能知道,您可以有多个连续的 when/then 对;在 then 块中完成的任何模拟实际上仅限于其 when 块。如果 Mocked 方法已经在 when/then 范围之外定义,会发生什么情况? then 块中定义的 Mock 优先。

恭喜!您偶然发现了 only 覆盖已建立的 Mocked values/methods 的方法。在新文档发布之前,我花了很长时间弄清楚它是如何工作的。

所以我们知道您正在覆盖将值定义为 return 的模拟。我们如何从这里开始?

given:
    def inner = Mock(Inner)
    1 * inner.greet() >> message 
expect:
    "hi" = inner.greet()
where:
    message = "hi"

离别的想法...我希望你不是在测试你在测试中设置的值。这实际上是断言 1 == 1。如果你想在测试行为时测试你的实际代码,我建议使用 Spy

given:
    def inner = Spy(Inner)
    1 * inner.greet() >> { 
        callRealMethod() // Actual method, read the documentation I linked
    }
expect:
    "hi" = inner.greet()