Groovy HttpBuilder-获取失败响应的主体

Groovy HttpBuilder-获取失败响应的主体,groovy,httpbuilder,Groovy,Httpbuilder,我试图使用Groovy HTTPBuilder编写一个集成测试,该测试将验证正文中是否返回了正确的错误消息以及HTTP 409状态消息。但是,我不知道在失败的情况下如何实际访问HTTP响应的主体 http.request(ENV_URL, Method.POST, ContentType.TEXT) { uri.path = "/curate/${id}/submit" contentType = ContentType.JSON response.failure = {

我试图使用Groovy HTTPBuilder编写一个集成测试,该测试将验证正文中是否返回了正确的错误消息以及HTTP 409状态消息。但是,我不知道在失败的情况下如何实际访问HTTP响应的主体

http.request(ENV_URL, Method.POST, ContentType.TEXT) {
    uri.path = "/curate/${id}/submit"
    contentType = ContentType.JSON
    response.failure = { failresp_inner ->
        failresp = failresp_inner
    }
}

then:
assert failresp.status == 409
// I would like something like 
//assert failresp.data == "expected error message"
这是来自服务器的HTTP响应的样子:

2013-11-13 18:17:58,726 DEBUG  wire - << "HTTP/1.1 409 Conflict[\r][\n]"
2013-11-13 18:17:58,726 DEBUG  wire - << "Date: Wed, 13 Nov 2013 23:17:58 GMT[\r][\n]"
2013-11-13 18:17:58,726 DEBUG  wire - << "Content-Type: text/plain[\r][\n]"
2013-11-13 18:17:58,726 DEBUG  wire - << "Transfer-Encoding: chunked[\r][\n]"
2013-11-13 18:17:58,727 DEBUG  wire - << "[\r][\n]"
2013-11-13 18:17:58,728 DEBUG  wire - << "E[\r][\n]"
2013-11-13 18:17:58,728 DEBUG  wire - << "expected error message"
2013-11-13 18:17:58,728 DEBUG  wire - << "[\r][\n]"
2013-11-13 18:17:58,728 DEBUG  wire - << "0[\r][\n]"
2013-11-13 18:17:58,728 DEBUG  wire - << "[\r][\n]"

2013-11-13 18:17:58726调试线-如果您使用:

response.failure = { resp, reader ->
    failstatus = resp.statusLine
    failresp   = reader.text
}

当我开始使用HttpBuilder时,我也遇到了这个问题。我提出的解决方案是定义HTTPBuilder成功和失败闭包,以返回如下一致的值:

HTTPBuilder http = new HTTPBuilder()
http.handler.failure = { resp, reader ->
    [response:resp, reader:reader]
}
http.handler.success = { resp, reader ->
    [response:resp, reader:reader]
}
def map = http.request(ENV_URL, Method.POST, ContentType.TEXT) {
    uri.path = "/curate/${id}/submit"
    contentType = ContentType.JSON
}

def response = map['response']
def reader = map['reader']

assert response.status == 409
因此,您的HTTPBuilder实例将一致地返回包含响应对象(HttpResponseDecorator实例)和读取器对象的映射。您的请求将如下所示:

HTTPBuilder http = new HTTPBuilder()
http.handler.failure = { resp, reader ->
    [response:resp, reader:reader]
}
http.handler.success = { resp, reader ->
    [response:resp, reader:reader]
}
def map = http.request(ENV_URL, Method.POST, ContentType.TEXT) {
    uri.path = "/curate/${id}/submit"
    contentType = ContentType.JSON
}

def response = map['response']
def reader = map['reader']

assert response.status == 409
读取器将是某种对象,它将允许您访问响应体,您可以通过调用getClass()方法来确定响应体的类型:


读取器对象的类型将由响应中的内容类型标头确定。您可以通过向请求中添加一个“Accept”头来明确告诉服务器您想要返回什么。

我最近在尝试使用Spock集成测试我的REST端点时遇到了这个问题。我用Sam的答案作为灵感,并最终对其进行了改进,以便继续利用HttpBuilder提供的自动铸造功能。在混乱了一段时间之后,我有了一个聪明的想法,将成功处理程序闭包分配给失败处理程序,以使行为标准化,而不管返回什么状态代码

client.handler.failure = client.handler.success
这方面的一个例子是:

...

import static org.apache.http.HttpStatus.*

...

private RESTClient createClient(String username = null, String password = null) {
    def client = new RESTClient(BASE_URL)
    client.handler.failure = client.handler.success

    if(username != null)
        client.auth.basic(username, password)

    return client
}

...

def unauthenticatedClient = createClient()
def userClient = createClient(USER_USERNAME, USER_PASSWORD)
def adminClient = createClient(ADMIN_USERNAME, ADMIN_PASSWORD)

...

def 'get account'() {
    expect:
    // unauthenticated tries to get user's account
    unauthenticatedClient.get([path: "account/$USER_EMAIL"]).status == SC_UNAUTHENTICATED

    // user gets user's account
    with(userClient.get([path: "account/$USER_EMAIL"])) {
        status == SC_OK
        with(responseData) {
            email == USER_EMAIL
            ...
        }
    }

    // user tries to get user2's account
    with(userClient.get([path: "account/$USER2_EMAIL"])) {
        status == SC_FORBIDDEN
        with(responseData) {
            message.contains(USER_EMAIL)
            message.contains(USER2_EMAIL)
            ...
        }
    }

    // admin to get user's account
    with(adminClient.get([path: "account/$USER_EMAIL"])) {
        status == SC_OK
        with(responseData) {
            email == USER_EMAIL
            ...
        }
    }
}

谢谢你的建议,我实际上已经尝试过了,这会导致闭包不再有正确的参数,所以整个方法都抛出了。非常简单!谢谢@Jon我不久前问了一个类似的问题,这个问题会从类似的答案中受益。如果我有机会,我会写出来的,但你可以随便告诉我。