diff --git a/core/spring-boot-test/src/main/java/org/springframework/boot/test/json/AbstractJsonMarshalTester.java b/core/spring-boot-test/src/main/java/org/springframework/boot/test/json/AbstractJsonMarshalTester.java index a16660e994f..3c687d6e76d 100644 --- a/core/spring-boot-test/src/main/java/org/springframework/boot/test/json/AbstractJsonMarshalTester.java +++ b/core/spring-boot-test/src/main/java/org/springframework/boot/test/json/AbstractJsonMarshalTester.java @@ -17,7 +17,6 @@ package org.springframework.boot.test.json; import java.io.BufferedReader; -import java.io.Closeable; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -298,7 +297,6 @@ public abstract class AbstractJsonMarshalTester { Assert.notNull(resource, "'resource' must not be null"); InputStream inputStream = resource.getInputStream(); T object = readObject(inputStream, getTypeNotNull()); - closeQuietly(inputStream); return new ObjectContent<>(this.type, object); } @@ -323,19 +321,9 @@ public abstract class AbstractJsonMarshalTester { verify(); Assert.notNull(reader, "'reader' must not be null"); T object = readObject(reader, getTypeNotNull()); - closeQuietly(reader); return new ObjectContent<>(this.type, object); } - private void closeQuietly(Closeable closeable) { - try { - closeable.close(); - } - catch (IOException ex) { - // Ignore - } - } - private void verify() { Assert.state(this.resourceLoadClass != null, "Uninitialized JsonMarshalTester (ResourceLoadClass is null)"); Assert.state(this.type != null, "Uninitialized JsonMarshalTester (Type is null)"); diff --git a/core/spring-boot-test/src/main/java/org/springframework/boot/test/json/GsonTester.java b/core/spring-boot-test/src/main/java/org/springframework/boot/test/json/GsonTester.java index ae56423670b..a3dab638bc2 100644 --- a/core/spring-boot-test/src/main/java/org/springframework/boot/test/json/GsonTester.java +++ b/core/spring-boot-test/src/main/java/org/springframework/boot/test/json/GsonTester.java @@ -86,7 +86,9 @@ public class GsonTester extends AbstractJsonMarshalTester { @Override protected T readObject(Reader reader, ResolvableType type) throws IOException { - return this.gson.fromJson(reader, type.getType()); + try (reader) { + return this.gson.fromJson(reader, type.getType()); + } } /** diff --git a/core/spring-boot-test/src/test/java/org/springframework/boot/test/json/AbstractJsonMarshalTesterTests.java b/core/spring-boot-test/src/test/java/org/springframework/boot/test/json/AbstractJsonMarshalTesterTests.java index 490b2d13d2d..30ab484e78a 100644 --- a/core/spring-boot-test/src/test/java/org/springframework/boot/test/json/AbstractJsonMarshalTesterTests.java +++ b/core/spring-boot-test/src/test/java/org/springframework/boot/test/json/AbstractJsonMarshalTesterTests.java @@ -18,6 +18,7 @@ package org.springframework.boot.test.json; import java.io.ByteArrayInputStream; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.StringReader; @@ -40,7 +41,12 @@ import org.springframework.util.FileCopyUtils; import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatException; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; /** * Tests for {@link AbstractJsonMarshalTester}. @@ -55,6 +61,8 @@ abstract class AbstractJsonMarshalTesterTests { private static final String ARRAY_JSON = "[" + JSON + "]"; + private static final String TRUNCATED_JSON = "{\"name\":\"Spring\","; + private static final ExampleObject OBJECT = createExampleObject("Spring", 123); private static final ResolvableType TYPE = ResolvableType.forClass(ExampleObject.class); @@ -145,6 +153,26 @@ abstract class AbstractJsonMarshalTesterTests { assertThat(tester.read(resource)).isEqualTo(OBJECT); } + @Test + void readResourceShouldCloseInputStream() throws IOException { + Resource resource = mock(); + InputStream stream = spy(new ByteArrayInputStream(JSON.getBytes())); + given(resource.getInputStream()).willReturn(stream); + AbstractJsonMarshalTester tester = createTester(TYPE); + assertThat(tester.read(stream)).isEqualTo(OBJECT); + then(stream).should().close(); + } + + @Test + void readResourceWhenReadFailsShouldCloseInputStream() throws IOException { + Resource resource = mock(); + InputStream stream = spy(new ByteArrayInputStream(TRUNCATED_JSON.getBytes())); + given(resource.getInputStream()).willReturn(stream); + AbstractJsonMarshalTester tester = createTester(TYPE); + assertThatException().isThrownBy(() -> tester.read(resource)); + then(stream).should().close(); + } + @Test void readReaderShouldReturnObject() throws Exception { Reader reader = new StringReader(JSON); @@ -152,6 +180,22 @@ abstract class AbstractJsonMarshalTesterTests { assertThat(tester.read(reader)).isEqualTo(OBJECT); } + @Test + void readReaderShouldCloseReader() throws IOException { + Reader reader = spy(new StringReader(JSON)); + AbstractJsonMarshalTester tester = createTester(TYPE); + assertThat(tester.read(reader)).isEqualTo(OBJECT); + then(reader).should().close(); + } + + @Test + void readReaderWhenReadFailsShouldCloseReader() throws IOException { + Reader reader = spy(new StringReader(TRUNCATED_JSON)); + AbstractJsonMarshalTester tester = createTester(TYPE); + assertThatException().isThrownBy(() -> tester.read(reader)); + then(reader).should().close(); + } + @Test void parseListShouldReturnContent() throws Exception { ResolvableType type = ResolvableTypes.get("listOfExampleObject");