Rest 如何在Grails2.4.3中的控制器中测试复合json对象响应
我正在测试Restful控制器的保存方法,Rest 如何在Grails2.4.3中的控制器中测试复合json对象响应,rest,grails,testing,junit,spock,Rest,Grails,Testing,Junit,Spock,我正在测试Restful控制器的保存方法,CustomerController 客户,域类,有地址关联,地址有城市,城市有州,州有国家 我为地址编写了自定义封送拆收器和自定义绑定帮助器,因此JSON客户是这样的: { "id": "g2c3e08iqton4v5bsgti33gkpd35l0er", "firstName": "Bob1", "lastName": "Patiño1", "middleName": "The Payaso1", "email
CustomerController
客户,域类,有地址关联,地址有城市,城市有州,州有国家
我为地址
编写了自定义封送拆收器和自定义绑定帮助器,因此JSON客户是这样的:
{
"id": "g2c3e08iqton4v5bsgti33gkpd35l0er",
"firstName": "Bob1",
"lastName": "Patiño1",
"middleName": "The Payaso1",
"email": "me@bobpatino.org",
"phoneNumber": "300555551",
"address": {
"addressLine1": "addressLine1",
"postalCode": "110111",
"city": {
"name": "Bogotá",
"state": "DC",
"country": "CO"
}
}
}
一切都在使用这种格式工作,记住地址的自定义封送拆收器和绑定帮助器,但现在我想测试控制器
@Unroll
void "create a new customer firstName: #firstName"(){
when: 'the merchantUser requests to create a new Customer'
controller.request.method = 'POST'
controller.request.contentType = JSON_CONTENT_TYPE
controller.request.JSON = [
firstName: firstName, lastName : lastName, middleName:middleName,
gender: gender, email: email, phoneNumber: phoneNumber, address: address
]
controller.save()
then:'The response code should be CREATED (201)'
controller.response.status == 201
and: 'The new customer should be returned'
controller.response.json.firstName == firstName
//TODO How to validate the address is added?
//controller.response.json.address == ????
1 * controller.springSecurityService.getPrincipal() >> merchantUser
where:
firstName|lastName|middleName|gender|email|phoneNumber|address
JSONObject.NULL |JSONObject.NULL |JSONObject.NULL |JSONObject.NULL |JSONObject.NULL |JSONObject.NULL|JSONObject.NULL
'bob' |'patiño'|'de' |'M' |'bob@patino.co'| '20055555'| [ addressLine1 :'addressLine1', postalCode:'110111',city :[name:'Bogotá',state:'DC',country:'CO']]
}
我的控制器保存方法是
@Transactional
def save() {
if(handleReadOnly()) {
return
}
def customer = createResource()
customer.merchant = MerchantUser.findByUsername(springSecurityService.getPrincipal().username)?.merchant
customer.validate()
if (customer.hasErrors()) {
respond customer.errors, [status: UNPROCESSABLE_ENTITY] // STATUS CODE 422
return
}
customer.save()
request.withFormat {
json {
respond customer, [status: CREATED] // STATUS CODE 201
}
}
}
如果我调试CustomerController,我发现客户资源是通过发送信息的有效地址创建的,事实上,如果我运行代码,它可以工作,但是在运行测试时,controller.response.json不包含Address对象
我还为客户和地址设置了模拟注释
这个问题也可能与在单元测试中使用自定义封送器有关。controller.response.json
如下所示
{
"middleName": "de",
"id": 1,
"lastName": "patiño",
"phoneNumber": "20055555",
"merchant": {
"id": 1,
"class": "models.Merchant"
},
"email": "bob@patino.co",
"address": {
"id": null,
"class": "models.Address"
},
"customerToken": "21jtdik0m99pnarth8g25meb423fmoh0",
"lastUpdated": null,
"gender": "M",
"dateCreated": null,
"class": "models.Customer",
"firstName": "bob"
}
我怀疑您正在
BootStrap.groovy
中注册自定义JSON封送器,该封送器未针对某些类型的测试执行(我不清楚确切的规则,也没有很好的文档记录)
避免此限制的一种方法是使用此处描述的
ObjectMarshallerRegisterer
方法:是的,我在Bootstrap.groovy中注册了自定义封送拆收器。我改变了你提到的文章中描述的方法,但仍然存在同样的问题。在开发或生产中运行时,它就像一个符咒,但在单元测试中,响应的地址只包含一个{“id”:null}
我认为marshallers不起作用,因为JSON响应就像取消发送默认的JSON封送器。我相信您需要从单元切换到集成测试,以便在(模拟)控制器响应中拾取并使用JSON封送器。另外,ObjectMarshallerRegisterer
方法的一个好处是,它极大地简化了单独测试封送器的任务(使用单元测试,而不是支付集成测试性能损失)。您是对的。在看到您的评论之前,我编写了集成测试,并且正在按它应该的方式工作。你认为这个问题仍然有效吗?我认为这个问题仍然有意义,因为我不是在测试封送员,而是在测试回复内容。是的,肯定是一个有效的问题。通常有很好的理由测试控制器响应(使用集成测试)和封送器(使用单元测试)。当您使用ObjectMarshallerRegisterer
而不是BootStrap.groovy
方法时,这两个级别的测试都成为可能。