【问题标题】:Test RestfulController with Grails使用 Grails 测试 RestfulController
【发布时间】:2014-05-28 15:51:50
【问题描述】:

我正在尝试为 Grails 2.4.0 中的 RestfulController 编写一些集成测试,以 JSON 格式响应。 index()-方法是这样实现的:

class PersonController extends RestfulController<Person> {
    ...
    def index(final Integer max) {
        params.max = Math.min(max ?: 10, 100)
        respond listAllResources(params), [includes: includeFields]
    }
    ...
}

集成测试如下所示:

void testListAllPersons() {
    def controller = new PersonController()
    new Person(name: "Person", age: 22).save(flush:true)
    new Person(name: "AnotherPerson", age: 31).save(flush:true)

    controller.response.format = 'json'
    controller.request.method = 'GET'

    controller.index()

    assertEquals '{{"name":"Person", "age": "22"},{"name":"AnotherPerson", "age": "31"}}', controller.response.json
}

我不明白的是 controller.response.json 只包含“AnotherPerson”而不是两个条目。 当我使用 run-app 启动服务器并使用 Rest-Client 对其进行测试时,我得到了两个条目。 有什么想法吗?

【问题讨论】:

  • 回复应该是JSONArray。您将其声明为无效的JSONObject。您能否也显示断言失败消息。

标签: json grails integration-testing


【解决方案1】:

您没有提供足够的信息来确定问题所在,但以下测试通过 2.4.0。

领域类:

// grails-app/domain/com/demo/Person.groovy
package com.demo

class Person {
    String name
    Integer age
}

控制器:

// grails-app/controllers/com/demo/PersonController.groovy
package com.demo

class PersonController extends grails.rest.RestfulController<Person> {

    PersonController() {
        super(Person)
    }

    def index(final Integer max) {
        params.max = Math.min(max ?: 10, 100)
        respond listAllResources(params)
    }
}

测试:

// test/unit/com/demo/PersonControllerSpec.groovy
package com.demo

import grails.test.mixin.TestFor
import spock.lang.Specification

@TestFor(PersonController)
@Mock(Person)
class PersonControllerSpec extends Specification {


    void "test index includes all people"() {
        given:
        new Person(name: "Person", age: 22).save(flush:true)
        new Person(name: "AnotherPerson", age: 31).save(flush:true)

        when:
        request.method = 'GET'
        response.format = 'json'
        controller.index()

        then:
        response.status == 200
        response.contentAsString == '[{"class":"com.demo.Person","id":1,"age":22,"name":"Person"},{"class":"com.demo.Person","id":2,"age":31,"name":"AnotherPerson"}]'
    }
}

【讨论】:

  • 您是否必须覆盖 personController 中的索引?您提供的实现与 RestfulController.respond listAllResources(params), model: [("${resourceName}Count".toString()): countResources()] 中的实现非常相似,您只是缺少资源计数。跨度>
  • "您是否必须覆盖 personController 中的索引?" - 我不认为我理解这个问题。索引操作在我上面展示的 PersonController 中定义。
  • 您上面的 PersonController 类扩展了 grails.rest.RestfulController。该类中的索引操作有一个默认实现。
  • 我认为你的答案是 100% 正确的。如果没有在 PersonController 中实现 index 方法,单元测试将失败。我一直在玩一些类似的代码,并且 RestfulController 超类在单元测试时返回一个空的域对象列表。但是当应用程序运行时,会返回完整的列表。您需要在子类中实现 index 方法才能使单元测试正常工作,这似乎有点奇怪。
  • 我在这里stackoverflow.com/questions/30044903/… 提出了一个新问题,该问题演示了必须在控制器中覆盖索引的问题。
【解决方案2】:

我把这个例子简化了一点。我使用了我在 bootstrap.groovy 中创建(不正确)的命名对象编组器,如下所示:

   JSON.createNamedConfig('simplePerson') { converterConfig ->
        converterConfig.registerObjectMarshaller(Person) {
            JSON.registerObjectMarshaller(Person) {
                def map = [:]
                map['name']  = it.name
                map['age']  = it.age
                return map
            }
        }
    }

并在控制器中使用它:

...
JSON.use("simplePerson")
...

通过像这样创建对象编组器来解决问题:

    JSON.createNamedConfig('simplePerson') { converterConfig ->
        converterConfig.registerObjectMarshaller(Person) {
            def map = [:]
            map['name']  = it.name
            map['age']  = it.age
            return map                
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-10
    • 2013-10-22
    • 2015-11-17
    • 1970-01-01
    • 1970-01-01
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多