验证Spock中的方法调用

时间:2014-07-22 00:15:17

标签: unit-testing grails spock

我试图测试应该在域类上调用方法的Grails控制器。以下是我的设置的示例:

域类:

class Vampire {

  def turnIntoBat() { ... }

}

控制器:

class VampireController {

  def transform(Vampire vampire) {
    ...
    vampire.turnIntoBat()
    ...
  }

}

测试:

void "Bat transformation"() {
  when:
  controller.request.json = new Vampire(...)
  controller.transform()

  then:
  //verify that turnIntoBat is invoked
  ...
}

从本次测试中可以看出,我使用JSON发送数据,因此模拟域类不会产生任何影响(在我尝试做的事情的背景下) 。或者,我可以致电controller.transform(mockVampire),但我想尽可能多地坚持上面那个,因为我也试图测试控制器的JSON / REST方面。

2 个答案:

答案 0 :(得分:0)

这里你有整个测试(使用模拟grails类):

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

import spock.lang.*

class Test extends Specification {

    void "test bat transformation"() {
      given:
      def controller = new VampireController()
      def vampire = GroovyMock(Vampire)

      when:
      controller.transform(vampire)

      then:
      1 * vampire.turnIntoBat()
    }   
}

class Vampire {
  def turnIntoBat() { }
}

class VampireController {
  def transform(Vampire vampire) {
    vampire.turnIntoBat()
  }
}

答案 1 :(得分:0)

问题是Grails正在创建传递给操作的Vampire命令对象。我们不能轻易窥探它。

我们可以使用这样的元编程:

class Vampire {
    def turnIntoBat () {
        [bat:true]
    }
}


@TestFor(FooController)
@Mock([Vampire])
class FooControllerSpec extends Specification {

    def "transforms vampire into bat manual meta programming" () {
        given:
        MetaMethod org = Vampire.metaClass.getMetaMethod('turnIntoBat')
        boolean calledTurnIntoBat = false
        Vampire.metaClass.turnIntoBat = { ->
            calledTurnIntoBat = true
            org.invoke delegate
        }

        request.method = 'POST'
        request.json = new Vampire()

        when:
        controller.transform()

        then:
        calledTurnIntoBat
        response.json.bat
    }
}

有点难看/吵闹,但它有效.. :)

spock文档讨论了GroovySpy这听起来像一个更简单的解决方案。我们可以传递一个global:true,它使spock拦截给定类的任何对象上的调用。

应该可以执行类似下面的代码,但我没有运行它(grails 2.4.2)。

@Ignore
def "transforms vampire into bat with GroovySpy" () {
    given:
    def anyVampire = GroovySpy (Vampire, global:true)

    request.method = 'POST'
    request.json = new Vampire()


    when:
    controller.transform()

    then:
    1 * anyVampire.turnIntoBat ()
    response.json.bat
}