From 417547e61a848c64623ee58bb49900f9ba1b2ece Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 28 Jun 2016 11:17:37 +0100 Subject: [PATCH] Support more types of content in RestAssuredRequestConverter Previously, RestAssuredRequestConverter only supported request and request part content that was null, a String or a byte[]. This was particularly problematic for multipart requests as RestAssured performs some internal conversion which meant that, no matter what the when a byte[] was provided it was wrapped in a ByteArrayInputStream meaning that the converter could not read it. The commit improves RestAssuredRequestConverter so that it will now convert File content and InputStream content where the stream supported reset(). Closes gh-252 --- .../RestAssuredRequestConverter.java | 38 ++++++++ .../RestAssuredRequestConverterTests.java | 96 +++++++++++++++++-- 2 files changed, 127 insertions(+), 7 deletions(-) diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredRequestConverter.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredRequestConverter.java index d2e60f0c..1673366a 100644 --- a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredRequestConverter.java +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredRequestConverter.java @@ -16,6 +16,9 @@ package org.springframework.restdocs.restassured; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.net.URI; import java.util.ArrayList; import java.util.Collection; @@ -35,6 +38,8 @@ import org.springframework.restdocs.operation.OperationRequestPart; import org.springframework.restdocs.operation.OperationRequestPartFactory; import org.springframework.restdocs.operation.Parameters; import org.springframework.restdocs.operation.RequestConverter; +import org.springframework.util.FileCopyUtils; +import org.springframework.util.StreamUtils; /** * A converter for creating an {@link OperationRequest} from a REST Assured @@ -64,6 +69,12 @@ class RestAssuredRequestConverter else if (content instanceof byte[]) { return (byte[]) content; } + else if (content instanceof File) { + return copyToByteArray((File) content); + } + else if (content instanceof InputStream) { + return copyToByteArray((InputStream) content); + } else if (content == null) { return new byte[0]; } @@ -73,6 +84,33 @@ class RestAssuredRequestConverter } } + private byte[] copyToByteArray(File file) { + try { + return FileCopyUtils.copyToByteArray(file); + } + catch (IOException ex) { + throw new IllegalStateException("Failed to read content from file " + file, + ex); + } + } + + private byte[] copyToByteArray(InputStream inputStream) { + try { + inputStream.reset(); + } + catch (IOException ex) { + throw new IllegalStateException("Cannot read content from input stream " + + inputStream + " due to reset() failure"); + } + try { + return StreamUtils.copyToByteArray(inputStream); + } + catch (IOException ex) { + throw new IllegalStateException( + "Failed to read content from input stream " + inputStream, ex); + } + } + private HttpHeaders extractHeaders(FilterableRequestSpecification requestSpec) { HttpHeaders httpHeaders = new HttpHeaders(); for (Header header : requestSpec.getHeaders()) { diff --git a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRequestConverterTests.java b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRequestConverterTests.java index 3bf79098..9c4f7615 100644 --- a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRequestConverterTests.java +++ b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRequestConverterTests.java @@ -18,6 +18,8 @@ package org.springframework.restdocs.restassured; import java.io.ByteArrayInputStream; import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.net.URI; import java.util.Arrays; import java.util.Collection; @@ -198,25 +200,105 @@ public class RestAssuredRequestConverterTests { } @Test - public void inputStreamBodyIsNotSupported() { + public void byteArrayInputStreamBody() { RequestSpecification requestSpec = RestAssured.given() .body(new ByteArrayInputStream(new byte[] { 1, 2, 3, 4 })) .port(this.port); requestSpec.post(); - this.thrown.expectMessage( - equalTo("Unsupported request content: java.io.ByteArrayInputStream")); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getContent(), is(equalTo(new byte[] { 1, 2, 3, 4 }))); + } + + @Test + public void fileBody() { + RequestSpecification requestSpec = RestAssured.given() + .body(new File("src/test/resources/body.txt")).port(this.port); + requestSpec.post(); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getContentAsString(), is(equalTo("file"))); + } + + @Test + public void fileInputStreamBody() throws FileNotFoundException { + FileInputStream inputStream = new FileInputStream("src/test/resources/body.txt"); + RequestSpecification requestSpec = RestAssured.given().body(inputStream) + .port(this.port); + requestSpec.post(); + this.thrown.expect(IllegalStateException.class); + this.thrown.expectMessage("Cannot read content from input stream " + inputStream + + " due to reset() failure"); this.factory.convert((FilterableRequestSpecification) requestSpec); } @Test - public void fileBodyIsNotSupported() { - RequestSpecification requestSpec = RestAssured.given() - .body(new File("src/test/resources/body.txt")).port(this.port); + public void multipartWithByteArrayInputStreamBody() { + RequestSpecification requestSpec = RestAssured.given().port(this.port) + .multiPart("foo", "foo.txt", new ByteArrayInputStream("foo".getBytes())); requestSpec.post(); - this.thrown.expectMessage(equalTo("Unsupported request content: java.io.File")); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getParts().iterator().next().getContentAsString(), + is(equalTo("foo"))); + } + + @Test + public void multipartWithStringBody() { + RequestSpecification requestSpec = RestAssured.given().port(this.port) + .multiPart("control", "foo"); + requestSpec.post(); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getParts().iterator().next().getContentAsString(), + is(equalTo("foo"))); + } + + @Test + public void multipartWithByteArrayBody() { + RequestSpecification requestSpec = RestAssured.given().port(this.port) + .multiPart("control", "file", "foo".getBytes()); + requestSpec.post(); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getParts().iterator().next().getContentAsString(), + is(equalTo("foo"))); + } + + @Test + public void multipartWithFileBody() { + RequestSpecification requestSpec = RestAssured.given().port(this.port) + .multiPart(new File("src/test/resources/body.txt")); + requestSpec.post(); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getParts().iterator().next().getContentAsString(), + is(equalTo("file"))); + } + + @Test + public void multipartWithFileInputStreamBody() throws FileNotFoundException { + FileInputStream inputStream = new FileInputStream("src/test/resources/body.txt"); + RequestSpecification requestSpec = RestAssured.given().port(this.port) + .multiPart("foo", "foo.txt", inputStream); + requestSpec.post(); + this.thrown.expect(IllegalStateException.class); + this.thrown.expectMessage("Cannot read content from input stream " + inputStream + + " due to reset() failure"); this.factory.convert((FilterableRequestSpecification) requestSpec); } + @Test + public void multipartWithObjectBody() { + RequestSpecification requestSpec = RestAssured.given().port(this.port) + .multiPart("control", new ObjectBody("bar")); + requestSpec.post(); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getParts().iterator().next().getContentAsString(), + is(equalTo("{\"foo\":\"bar\"}"))); + } + /** * Minimal test web application. */