我试图测试应该在域类上调用方法的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方面。
答案 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
}