Spock - 存根 JSON 响应
Spock - stubbing the JSON response
我使用带有内置 spock 的 Grails 3.1.7。看起来我在对单元测试执行期间由控制器呈现的 return 服务值进行存根时遇到了麻烦。服务方法 returns null 然后控制器抛出 GroovyRuntimeException 抱怨 "Cannot resolve which method to invoke" 因为 "null" returned.
控制器动作代码示例:
def register(RequestRegistrationCommand rrc) {
//some logic
render ajaxResponseService.composeJsonResponse(rrc)
}
服务方法代码示例:
JSON composeJsonResponse(instance, String successMessage = null) {
//some logic
[success: success, messages: messages] as JSON
}
部分测试套件代码:
//field definitions
def requestRegistrationCommand = Mock(RequestRegistrationCommand)
def ajaxResponseService = Mock(AjaxResponseService)
def setup() {
controller.ajaxResponseService = ajaxResponseService
.....
}
void "Testing register() action"() {
when: 'Passing invalid register params'
...
params.email = INVALID_EMAIL
controller.register(requestRegistrationCommand)
then: 'JSON response returned'
...
1 * ajaxResponseService.composeJsonResponse(requestRegistrationCommand) >> [asd:123] as JSON //tried plenty of things here
}
有趣的是交互本身被触发(通过将其替换为“0 * _”进行检查,并将“1 * ajaxR ... >> 'asd'”放入错误中字符串无法转换为 JSON)。因此,交互可能具有 return 一些存根值,但无论如何在大多数情况下,我尝试过控制器的行为就好像它试图呈现 null:
groovy.lang.GroovyRuntimeException: Ambiguous method overloading for
method
grails.artefact.controller.support.ResponseRenderer$Trait$Helper#render.
Cannot resolve which method to invoke for [class
com.tempvs.controllers.AuthController, null] due to overlapping
prototypes between: [interface
grails.artefact.controller.support.ResponseRenderer, interface
java.lang.CharSequence] [interface
grails.artefact.controller.support.ResponseRenderer, interface
java.util.Map] [interface
grails.artefact.controller.support.ResponseRenderer, interface
org.grails.web.converters.Converter] at
com.tempvs.controllers.AuthController.register(AuthController.groovy:45)
at com.tempvs.controllers.AuthControllerSpec.Testing register()
action(AuthControllerSpec.groovy:97)
我做错了什么以及我应该如何强制模拟服务对象 return 非空值以避免控制器渲染失败?
如果需要更多信息,请通知我,我尽量做到简短。提前致谢!
UPD
交互测试通过:
1 * ajaxResponseService.composeJsonResponse(requestRegistrationCommand) >> Mock(JSON)
当我将 AjaxResponseService#composeJsonResponse() return 类型从 JSON 更改为 def 时。但是来吧,我只使用一个模拟的协作者进行测试,我怎么能强制它支持显式类型?!?!
您应该为您的 return 值使用闭包:
1 * ajaxResponseService.composeJsonResponse(requestRegistrationCommand) >> { [asd:123] as JSON }
参见(请参阅有关 return 值的部分):
http://spockframework.org/spock/docs/1.1-rc-3/interaction_based_testing.html
您可以用括号将 return 括起来:
1 * ajaxResponseService.composeJsonResponse(requestRegistrationCommand) >> ( [asd:123] as JSON )
实际上我通过模拟 return 值解决了它:
def json = Mock(JSON)
....
1 * ajaxResponseService.composeJsonResponse(requestRegistrationCommand) >> json
我使用带有内置 spock 的 Grails 3.1.7。看起来我在对单元测试执行期间由控制器呈现的 return 服务值进行存根时遇到了麻烦。服务方法 returns null 然后控制器抛出 GroovyRuntimeException 抱怨 "Cannot resolve which method to invoke" 因为 "null" returned.
控制器动作代码示例:
def register(RequestRegistrationCommand rrc) {
//some logic
render ajaxResponseService.composeJsonResponse(rrc)
}
服务方法代码示例:
JSON composeJsonResponse(instance, String successMessage = null) {
//some logic
[success: success, messages: messages] as JSON
}
部分测试套件代码:
//field definitions
def requestRegistrationCommand = Mock(RequestRegistrationCommand)
def ajaxResponseService = Mock(AjaxResponseService)
def setup() {
controller.ajaxResponseService = ajaxResponseService
.....
}
void "Testing register() action"() {
when: 'Passing invalid register params'
...
params.email = INVALID_EMAIL
controller.register(requestRegistrationCommand)
then: 'JSON response returned'
...
1 * ajaxResponseService.composeJsonResponse(requestRegistrationCommand) >> [asd:123] as JSON //tried plenty of things here
}
有趣的是交互本身被触发(通过将其替换为“0 * _”进行检查,并将“1 * ajaxR ... >> 'asd'”放入错误中字符串无法转换为 JSON)。因此,交互可能具有 return 一些存根值,但无论如何在大多数情况下,我尝试过控制器的行为就好像它试图呈现 null:
groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method grails.artefact.controller.support.ResponseRenderer$Trait$Helper#render. Cannot resolve which method to invoke for [class com.tempvs.controllers.AuthController, null] due to overlapping prototypes between: [interface grails.artefact.controller.support.ResponseRenderer, interface java.lang.CharSequence] [interface grails.artefact.controller.support.ResponseRenderer, interface java.util.Map] [interface grails.artefact.controller.support.ResponseRenderer, interface org.grails.web.converters.Converter] at com.tempvs.controllers.AuthController.register(AuthController.groovy:45) at com.tempvs.controllers.AuthControllerSpec.Testing register() action(AuthControllerSpec.groovy:97)
我做错了什么以及我应该如何强制模拟服务对象 return 非空值以避免控制器渲染失败?
如果需要更多信息,请通知我,我尽量做到简短。提前致谢!
UPD 交互测试通过:
1 * ajaxResponseService.composeJsonResponse(requestRegistrationCommand) >> Mock(JSON)
当我将 AjaxResponseService#composeJsonResponse() return 类型从 JSON 更改为 def 时。但是来吧,我只使用一个模拟的协作者进行测试,我怎么能强制它支持显式类型?!?!
您应该为您的 return 值使用闭包:
1 * ajaxResponseService.composeJsonResponse(requestRegistrationCommand) >> { [asd:123] as JSON }
参见(请参阅有关 return 值的部分):
http://spockframework.org/spock/docs/1.1-rc-3/interaction_based_testing.html
您可以用括号将 return 括起来:
1 * ajaxResponseService.composeJsonResponse(requestRegistrationCommand) >> ( [asd:123] as JSON )
实际上我通过模拟 return 值解决了它:
def json = Mock(JSON)
....
1 * ajaxResponseService.composeJsonResponse(requestRegistrationCommand) >> json