简体   繁体   English

有没有办法将 groovy 闭包作为变量注入 Spock 模拟谓词参数

[英]Is there a way to inject a groovy closure as variable into Spock mock predicate argument

I found an interesting line in Spock interactions documentation:我在 Spock 交互文档中发现了一行有趣的内容:

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

last line of constraints, example with closure predicate:最后一行约束,带有闭包谓词的示例:

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

My question is: is there a way in Groovy to pass this predicate as variable?我的问题是: Groovy 中有没有办法将此谓词作为变量传递?

My testing environment code:我的测试环境代码:

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
   }
}

and test code:和测试代码:

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

      when:
      s.doSth(2)

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

what I would like to achieve:我想实现的目标:

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
   }

The closure takes an argument, as indicated by it having a defined value.闭包接受一个参数,正如it具有定义的值所指示的那样。 That value is the corresponding method parameter.该值是相应的方法参数。 So whatever closure you define outside of your interaction, you need to make sure that the interaction hands over that parameter to the closure, ie you need to create your own (small and simple) closure evaluating the outer (potentially lengthier, more complex) closure with the parameter it :因此,无论您在交互之外定义什么闭包,您都需要确保交互将该参数传递给闭包,即您需要创建自己的(小而简单的)闭包来评估外部(可能更长、更复杂)的闭包使用参数it

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

Sorry for the repetition, but I always prefer a full MCVE in my answers so you can easily copy, paste, compile and run:抱歉重复,但我总是更喜欢在我的答案中使用完整的MCVE ,以便您可以轻松复制、粘贴、编译和运行:

Application classes:应用类:

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 specification:斯波克规格:

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
  }
}

Console log:控制台日志:

some test: closure parameter = 2
another test: closure parameter = 2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM