控制器(用于休息api)的Grails集成测试不起作用

Joh*_*tle 6 rest grails integration-testing

Grails 2.4.4.我们有很多JSON/REST API端点,如下所示,但代码更多(注意:我们不能使用RestfulController,因为我们有SpringSecurity而且它们不兼容)

例如

class SessionController 
def sessionService
static namespace = 'v1'
static allowedMethods = [loginPlayer: "POST"]

def loginPlayer()  {
    def payload = request.JSON

    try {
        // Check params are there.
        if (payload.user == null) {
            render(status: 422, contentType: 'application/json') {
                 [
                  'result'     : -1
                  'description': "missing params"
                 ]
            return
        }

        def result = sessionService.loginPlayer(
                    payload.user,
                    payload.password
            )

        if (result.returnCode == 0) {
                render(status: 200, contentType: 'application/json') {
                    [
                      'result' : 0
                      'authToken' : result.authToken
       etc.
Run Code Online (Sandbox Code Playgroud)

我们目前正在使用SOAPUI手动测试它们.我们迫切希望自动化集成测试能够针对数据库测试整个API的端到端.

我们试过这个:

class SessionControllerIntegrationSpec extends IntegrationSpec {
    SessionController controller
    def setup() {
    }

    def cleanup() {
    }

    void "test login"() {
        controller = new SessionController()
        controller.request.contentType = 'application/json'
        controller.request.format = 'json'
        controller.response.format = 'json'

        when:
        controller.request.content =
                '{"user":"someuser","password":"somepass"}'.getBytes()

        def model = controller.loginPlayer()

        then:
        model != null
    }
}
Run Code Online (Sandbox Code Playgroud)

但它总是返回null作为模型.

还尝试过:

class SessionControllerIntegrationSpec extends GroovyTestCase {
:
def sessionService
:
controller.sessionService = sessionService
Run Code Online (Sandbox Code Playgroud)

按照传递" 使用服务测试控制器 "的说明

但这没有帮助 - 结果仍然无效.同时扩展GroovyTestCase意味着回到断言.

我们正在尝试做甚么可能吗?

我们看到有些人通过点击localhost的外部URL进行集成测试,例如:

class ExampleWebAppSpecification extends Specification {
    def "Should return 200 & a message with the input appended"() {

        setup:
             def primerEndpoint = new RESTClient( 'http://localhost:8080/' )
        when:
             def resp = primerEndpoint.get([ path: 'exampleendpoint', query : [ input : 'Get a hair cut' ]])
        then:
             with(resp) {
                 status == 200
                 contentType == "application/json"
             }
             with(resp.data) {
                 payload == "Something really important: Get a hair cut"
             }
    } }
Run Code Online (Sandbox Code Playgroud)

这与使用jmeter或其他工具测试正在运行的服务器并没有太大的不同,并且具有很多依赖性.

任何提示或建议?

更新1:

找到了一个这样做的例子

 assert controller.response.getStatus() == 200
Run Code Online (Sandbox Code Playgroud)

在调试器中,controller.response.getStatus()返回405(我们的控制器永远不会返回的状态),controller.response.contentAsString返回"".

当我们在调试器中运行测试时,永远不会调用Controllers代码.所以问题可能是grails根本没有注入SessionController.

更新2

猜测问题与请求方法有关,尝试添加:

    controller.request.requestMethod = HttpMethod.POST
Run Code Online (Sandbox Code Playgroud)

但是,这仍然会产生405.

在REST控制器中,我们有:

static allowedMethods = [loginPlayer: "POST"]
Run Code Online (Sandbox Code Playgroud)

如果我对此发表评论,我会收到预期的回复!

所以问题是现在如何让测试使用POST(设置requestMethod似乎没有这样做),或者如果控制器在测试模式下如何更改控制器以接受GET?

更新3 - 解决了!工作代码如下:

class SessionControllerIntegrationSpec扩展了IntegrationSpec def sessionService

class SessionControllerIntegrationSpec extends IntegrationSpec {
    SessionController controller

    void "test login"() {
        controller = new SessionController() // must manually create
        controller.sessionService = sessionService // must manually inject

        controller.request.contentType = 'application/json'
        controller.request.format = 'json'
        controller.response.format = 'json'
        controller.request.requestMethod = HttpMethod.POST
        controller.request.method = 'POST'


        when:
        controller.request.content =
                '{"user":"someuser","password":"somepass"}'.getBytes()

        then:
        assert controller.response.getStatus() == 200
        print "CONTENT: " + controller.response.contentAsString
        // now can use string search functions to check the JSON data returned.
Run Code Online (Sandbox Code Playgroud)