0

I have some automated tests that use HttpURLConnection to exercise a RESTful API.

Part of my code (below) asserts that the the response returns a certain HTTP Response code. I am expecting a HTTP 206 Response, but getResponseCode is always returning 200. However if I hit the url directly using curl, I get 'HTTP/1.1 206 Partial Content' as expected.

    URL requestURL = new URL(url);
    HttpURLConnection connection = (HttpURLConnection) requestURL.openConnection();
    try {
        connection.setRequestProperty("Connection", "close");
        connection.setReadTimeout(5000);

        assertEquals("Request successfully handled", 
                expectedResponseCode, 
                connection.getResponseCode());

        InputStream input = connection.getInputStream();
        try {
            return toString(input);
        } finally {
            input.close();
        }
    } finally {
        connection.disconnect();
    }

Any ideas on why this is happening and how to get the behaviour I want?

4

3 に答える 3

1

Try connection.getResponseMessage() method? It will probably contain the REST response where the actual code is found. The connection response may have come, but the actual operation response can be found in the message.

于 2012-05-25T17:49:20.190 に答える
1

投稿したコードは期待どおりに動作します。これを証明する完全なテストケースを次に示します。

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.URL;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;

public class Http206Test {
    private HttpServer server;

    @Before
    public void setUp() throws Exception {
        server = HttpServer.create(new InetSocketAddress(8080), 0);
        server.createContext("/", new HttpHandler() {
            public void handle(HttpExchange t) throws IOException {
                t.sendResponseHeaders(206, 0);
                t.getResponseBody().write("I'm a 206 response".getBytes());
                t.getResponseBody().close();
            }
        });
        server.start();
    }

    @After
    public void tearDown() throws Exception {
        server.stop(1);
    }

    @Test
    public void httpUrlConnection206Response() throws Exception {
        String body = getContent("http://localhost:8080", 206);
        assertThat(body, equalTo("I'm a 206 response"));
    }

    @Test(expected = AssertionError.class)
    public void httpUrlConnection205Response() throws Exception {
        getContent("http://localhost:8080", 205);
    }

    public String getContent(String url, int expectedResponseCode) throws IOException {
        URL requestURL = new URL(url);
        HttpURLConnection connection = (HttpURLConnection) requestURL.openConnection();
        try {
            connection.setRequestProperty("Connection", "close");
            connection.setReadTimeout(5000);
            assertEquals("Request successfully handled",
                    expectedResponseCode,
                    connection.getResponseCode());
            InputStream input = connection.getInputStream();
            try {
                return toString(input);
            } finally {
                input.close();
            }
        } finally {
            connection.disconnect();
        }
    }

    public String toString(InputStream stream) throws IOException {
        int data;
        StringBuilder builder = new StringBuilder();
        while ((data = stream.read()) != -1) {
            builder.append((char) data);
        }
        return builder.toString();
    }
}

これは、テストが正しく、サービスに問題があることを意味します。

于 2012-05-25T18:08:54.437 に答える
1

問題は、応答コードを設定する前に write() を呼び出していたことです。これは curl で使用すると機能するように見えますが、単体テストでは機能しません。これは、コードが入力を取得した直後に戻りコードをアサートするためです。

問題コード:

String responseMessage = response.getMessage();
OutputStreamWriter out = new OutputStreamWriter(httpResponse.getOutputStream());
out.write(responseMessage);
out.close();
httpResponse.setContentType("application/json");
httpResponse.setContentLength(responseMessage.length());
httpResponse.setStatus(response.getResponseCode());

固定コード:

httpResponse.setStatus(response.getResponseCode()); //Do this first!
String responseMessage = response.getMessage();
OutputStreamWriter out = new OutputStreamWriter(httpResponse.getOutputStream());
out.write(responseMessage);
out.close();
httpResponse.setContentType("application/json");
httpResponse.setContentLength(responseMessage.length());
于 2012-05-25T18:30:43.093 に答える