2012-05-25 4 views
0

HttpURLConnection을 사용하여 RESTful API를 사용하는 자동화 된 테스트가 있습니다.HttpURLConnection.getResponseCode가 HTTP 응답 코드 206을 수신하지 않습니다.

내 코드 부분 (아래)은 응답이 특정 HTTP 응답 코드를 반환한다고 주장합니다. HTTP 206 응답을 기대하고 있지만 getResponseCode는 항상 200을 반환합니다. 그러나 내가 컬을 사용하여 URL을 직접 친다면 예상대로 'HTTP/1.1 206 Partial Content'를 얻습니다.

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(); 
    } 

왜 이런 일이 일어나고 원하는 동작을 얻으려는 아이디어가 있습니까?

답변

1

그래서 문제는 내가 응답 코드를 설정하기 전에 write()를 호출하고 있다는 것이 었습니다. 이것이 곱슬 곱슬하게 사용될 때 작동하는 것처럼 보일지라도, 코드가 입력을 얻은 직후 반환 코드를 나타 내기 때문에 단위 테스트에서는 작동하지 않습니다.

문제 코드 :

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()); 
+0

허, 누가 쥐었 을까요. 당신이 그것을 알아 낸 것을 기쁘게 생각합니다! – kentcdodds

+2

응답 코드는 HTTP 응답의 첫 번째 줄에 있습니다. 스트림 버퍼가 플러시되도록 충분한 내용을 작성하면 (즉, 응답의 일부가 클라이언트로 다시 전송 됨) 응답 코드를 설정하기에는 너무 늦습니다. 분명히 컬이 당신의 코드와 다른 방식으로 요청을하고 있었고 어떻게 든 버퍼링이 다르게 행동하게 만들었습니다. 다른 것을 보지 않고서는 컨텐츠 인코딩과 관련 될 수 있다고 추측합니다. –

+0

상태 코드를 설정하는 코드가 너무 늦게 실행 된 경우 헤더 필드를 설정하는 경우에도 동일하게 적용해야합니다. –

1

시도 connection.getResponseMessage() 방법? 실제 코드가있는 곳에 REST 응답을 포함 할 것입니다. 연결 응답이 올 수도 있지만 메시지에서 실제 작업 응답을 찾을 수 있습니다.

+0

getResponseMessage() 반환은, '확인'을 사용하고있는 편안하고 API가 무엇 getResponseCode() 반환 (200) – Oleksi

+0

과 일치하는 ? – kentcdodds

+0

내가 작성한 API입니다. 아무것도 공개하지 않습니다. – Oleksi

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(); 
    } 
} 

이는 테스트 결과가 정확하고 서비스에 문제가 있음을 의미합니다.

+0

흥미 롭습니다. 동일한 URL에 컬을 사용하여 GET을 만드는 이유는 무엇입니까? 아마도 일부 머리글이나 다른 것을 설정하지 않은 것입니까? – Oleksi

+0

그것을 알아 냈습니다. 여기에 자체 답변을 참조하십시오 : http://stackoverflow.com/a/10759669/1165637 – Oleksi