是否可以将Groovy闭包作为变量注入Spock模拟谓词参数中

问题描述 投票:1回答:1

我在Spock交互文档中找到了有趣的一行:

http://spockframework.org/spock/docs/1.3/interaction_based_testing.html#_argument_constraints

约束的最后一行,带有关闭谓词的示例:

1 * subscriber.receive({ it.size() > 3 && it.contains('a') })

我的问题是:Groovy中是否有一种方法可以将此谓词作为变量传递?

我的测试环境代码:

class Something {
   Doer doer

   Something(Doer doer) {
      this.doer = doer
   }

   boolean doSth(x) {
      if (!doer.validate(x)) throw new RuntimeException()
      true
   }
}

class Doer {
   boolean validate(int x) {
      x == 2
   }
}

和测试代码:

   def "some test"() {
      given:
      def d = Mock(Doer)
      def s = new Something(d)

      when:
      s.doSth(2)

      then:
      1 * d.validate({ it == 2 }) >> true
   }

我想实现的目标:

def "some test"() {
      given:
      def d = Mock(Doer)
      def s = new Something(d)
      def myClosureVar = { ??? }

      when:
      s.doSth(2)

      then:
      1 * d.validate(myClosureVar) >> true
   }
groovy closures spock
1个回答
2
投票
闭包接受一个自变量,如it所定义的值。该值是相应的方法参数。因此,无论您在交互之外定义了什么闭合,都需要确保交互将该参数移交给闭合,即,您需要创建自己的(小而简单的)闭合来评估外部(可能更长,更复杂)的闭合使用参数it

1 * d.validate({ myClosureVar(it) }) >> true

很抱歉重复,但是我总是希望答案中带有完整的MCVE,以便您可以轻松地复制,粘贴,编译和运行:

应用程序类:

package de.scrum_master.stackoverflow.q60341734 class Doer { boolean validate(int x) { x == 2 } }
package de.scrum_master.stackoverflow.q60341734

class Something {
  Doer doer

  Something(Doer doer) {
    this.doer = doer
  }

  boolean doSth(x) {
    if (!doer.validate(x)) throw new RuntimeException()
    true
  }
}

Spock规范:

package de.scrum_master.stackoverflow.q60341734 import org.junit.Rule import org.junit.rules.TestName import spock.lang.Specification class SomethingTest extends Specification { @Rule TestName testName def "some test"() { given: def d = Mock(Doer) def s = new Something(d) when: s.doSth(2) then: 1 * d.validate({ println "$testName.methodName: closure parameter = $it"; it == 2 }) >> true } def "another test"() { given: def d = Mock(Doer) def s = new Something(d) def myClosureVar = { println "$testName.methodName: closure parameter = $it"; it == 2 } when: s.doSth(2) then: 1 * d.validate({ myClosureVar(it) }) >> true } }

控制台日志:

some test: closure parameter = 2 another test: closure parameter = 2
© www.soinside.com 2019 - 2024. All rights reserved.