I have a class in my javax servlet application that serves as a proxy and creates multipart form data for POST requests. During regression tests (actual calls to the servlet) the application performs as expected, however, my unit test continues to fail. This is the line in my unit test that throws the exceptionString httpPostBody = IOUtils.toString(httpPost.getEntity().getContent()); It's specifically httpPost.getEntity().getContent().
Full Unit Test
@Test
public void testCreatePostRequest() throws IOException, ServletException, URISyntaxException, NullPointerException {
URI newTargetUri = new URI(targetUriPost);
cdsRequestBuilder = new CDSRequestBuilder();
HttpPost httpPost = cdsRequestBuilder.createPostRequest(mockClientRequest, newTargetUri);
// Parse the entity
String httpPostBody = IOUtils.toString(httpPost.getEntity().getContent());
// Perform evaluation
Assert.assertNotNull(httpPost);
Assert.assertEquals(httpPost.getHeaders(HttpHeaders.HOST)[0].toString(), ("Host: " + newTargetUri.getHost()));
Assert.assertTrue(httpPost.getHeaders(HttpHeaders.CONTENT_LENGTH).length == 0);
Assert.assertTrue(httpPostBody.contains("payload"));
Assert.assertTrue(httpPostBody.contains("file"));
Assert.assertTrue(httpPostBody.contains(testFileBinaryData));
}
Method that is tested calls this method
private HttpEntity convertInputStreamToMultiPart(Collection<Part> clientParts, String boundary) throws IOException {
Part payload = null;
Part file = null;
for (Part part : clientParts) {
if (part.getName().equalsIgnoreCase("payload")) {
payload = part;
} else if (part.getName().equalsIgnoreCase("file")) {
file = part;
}
}
if(payload == null) {
logIt.error("Failed to extract payload - no payload found");
throw new IllegalStateException("Payload is missing from client request.");
}
if(file == null || file.getSubmittedFileName().length() == 0) {
logIt.error("Failed to extract file - no file found");
throw new IllegalStateException("File is missing from client request.");
}
logIt.info("Payload is parsed from client: {}", IOUtils.toString(payload.getInputStream()));
return MultipartEntityBuilder.create()
.addTextBody("payload", IOUtils.toString(payload.getInputStream()))
.addBinaryBody("file", file.getInputStream(), ContentType.parse("application/pdf"), file.getSubmittedFileName())
.setContentType(ContentType.parse(MediaType.APPLICATION_FORM_URLENCODED))
.setBoundary(boundary)
.build();
}
This unit test passed fine previously when I was temporarily saving the file input stream to a File object and then using that to populate the binary body, but as a result of performance tests, I decided to simply pass in the file input stream itself. Note, that in my unit test, I mock the file input stream as such:
Part mockFilePart = mock(Part.class);
when(mockFilePart.getName()).thenReturn("file");
when(mockFilePart.getSubmittedFileName()).thenReturn(testFileName);
when(mockFilePart.getInputStream()).thenReturn(IOUtils.toInputStream(testFileBinaryData));
Full Exception
org.apache.http.ContentTooLongException: Content length is unknown
at org.apache.http.entity.mime.MultipartFormEntity.getContent(MultipartFormEntity.java:101)
at gov.va.cds.test.CDSRequestBuilderTest.testCreatePostRequest(CDSRequestBuilderTest.java:117)
FIXED! So since httpPost.getEntity().getContent() will always have an unknown content length before the request is finally sent, I looked at other ways to get the content and that was by using a ByteArrayOutputStream. I then do a couple conversions to get it back to a String to perform my assertions. The unit test now looks like this.