Spring Boot test - MockHttpServletResponse getContentLength return 0 despite of content

Viewed 589

I notice that in Spring Boot testing, the getContentLength() of MockHttpServletResponse, same as javax.servlet.http.HttpServletResponse, only reads the request header "Content-Length" to determine the returned value, but if in my test I don't set the header, it returns 0, ignoring whether there is any content.

@Then("xxxxx returns {string} and status code {int}")
public void xxxxx_returns_and_status_code(String result, Integer code) throws Exception {
    assertThat(this.results.getResponse().getContentType()).isEqualTo(MediaType.APPLICATION_JSON_UTF8_VALUE); // <-- pass
    assertThat(this.results.getResponse().getStatus()).isEqualTo(code); // <-- pass

    System.out.println(this.results.getResponse().getContentLength()); // 0???
    System.out.println(this.results.getResponse().getContentAsString()); // the correct response

    assertThat(this.results.getResponse().getContentLength()).isNotEqualTo(0); // not pass, confusing
    getContentAsString()// pass
}

It, is standard, but somehow confusing.

To make the test pass, I have to do:

assertThat(this.results.getResponse().getContentAsString().length()).isNotEqualTo(0);

Why it was implemented this way?

1 Answers

It MIGHT be the case, that the Integer conversion of the value HttpHeaders.CONTENT_LENGTH which is executed in the class leads to this behavior. This is the code setting the value for contentLength (which is initiated and resetted to 0):

else if (HttpHeaders.CONTENT_LENGTH.equalsIgnoreCase(name)) {
            setContentLength(value instanceof Number ? ((Number) value).intValue() :
                    Integer.parseInt(value.toString()));
            return true;
}

Maybe getContentLengthLong will help your problem?

Check out the implementation on: https://github.com/spring-projects/spring-framework/blob/master/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java

Related