From 92e16f9765fa01f4fe4feea111509398c03ec7e8 Mon Sep 17 00:00:00 2001 From: Scott Leberknight <174812+sleberknight@users.noreply.github.com> Date: Wed, 31 Jul 2024 15:52:08 +0000 Subject: [PATCH] Cleanup and enhance exception message --- src/main/java/org/kiwiproject/io/KiwiIO.java | 14 ++++--- .../java/org/kiwiproject/io/KiwiIOTest.java | 39 ++++++++++++++++--- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/kiwiproject/io/KiwiIO.java b/src/main/java/org/kiwiproject/io/KiwiIO.java index e31f9a29..6edaf492 100644 --- a/src/main/java/org/kiwiproject/io/KiwiIO.java +++ b/src/main/java/org/kiwiproject/io/KiwiIO.java @@ -235,7 +235,7 @@ public static void closeObjectsQuietly(String closeMethodName, Object... objects return; } - checkDoesNotContainAnyCloseableResources(objects); + checkDoesNotContainAnyCloseableResources(closeMethodName, objects); Arrays.stream(objects) .filter(Objects::nonNull) @@ -243,15 +243,17 @@ public static void closeObjectsQuietly(String closeMethodName, Object... objects .forEach(KiwiIO::closeQuietly); } - private static void checkDoesNotContainAnyCloseableResources(Object... objects) { + private static void checkDoesNotContainAnyCloseableResources(String closeMethodName, Object... objects) { for (var object : objects) { - checkIsNotCloseableResource(object); + checkIsNotCloseableResource(closeMethodName, object); } } - private static void checkIsNotCloseableResource(Object object) { - checkArgument(isNotCloseableResource(object), - "objects should not contain any instances of CloseableResource when a single closeMethodName is specified"); + private static void checkIsNotCloseableResource(String closeMethodName, Object object) { + checkArgument( + isNotCloseableResource(object), + "objects should not contain any instances of CloseableResource when a single closeMethodName (%s) is specified", + closeMethodName); } private static boolean isNotCloseableResource(Object object) { diff --git a/src/test/java/org/kiwiproject/io/KiwiIOTest.java b/src/test/java/org/kiwiproject/io/KiwiIOTest.java index 8df0f968..a3eb7f03 100644 --- a/src/test/java/org/kiwiproject/io/KiwiIOTest.java +++ b/src/test/java/org/kiwiproject/io/KiwiIOTest.java @@ -7,8 +7,10 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import org.junit.jupiter.api.BeforeEach; @@ -21,7 +23,6 @@ import org.kiwiproject.io.KiwiIO.CloseableResource; import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; @@ -71,6 +72,7 @@ void shouldClose_Reader_WhenThrowsOnClose() throws IOException { var reader = mock(Reader.class); doThrow(new IOException("I cannot read")).when(reader).close(); assertThatCode(() -> KiwiIO.closeQuietly(reader)).doesNotThrowAnyException(); + verify(reader).close(); } @SuppressWarnings("ConstantValue") @@ -91,6 +93,7 @@ void shouldClose_Writer_WhenThrowsOnClose() throws IOException { var writer = mock(Writer.class); doThrow(new IOException("I cannot write")).when(writer).close(); assertThatCode(() -> KiwiIO.closeQuietly(writer)).doesNotThrowAnyException(); + verify(writer).close(); } @SuppressWarnings("ConstantValue") @@ -111,6 +114,7 @@ void shouldClose_InputStream_WhenThrowsOnClose() throws IOException { var stream = mock(InputStream.class); doThrow(new IOException("I cannot read")).when(stream).close(); assertThatCode(() -> KiwiIO.closeQuietly(stream)).doesNotThrowAnyException(); + verify(stream).close(); } @SuppressWarnings("ConstantValue") @@ -131,6 +135,7 @@ void shouldClose_OutputStream_WhenThrowsOnClose() throws IOException { var stream = mock(OutputStream.class); doThrow(new IOException("I cannot stream")).when(stream).close(); assertThatCode(() -> KiwiIO.closeQuietly(stream)).doesNotThrowAnyException(); + verify(stream).close(); } @SuppressWarnings("ConstantValue") @@ -152,6 +157,7 @@ void shouldClose_Socket_WhenThrowsOnClose() throws IOException { var socket = mock(Socket.class); doThrow(new IOException("I cannot read")).when(socket).close(); assertThatCode(() -> KiwiIO.closeQuietly(socket)).doesNotThrowAnyException(); + verify(socket).close(); } @SuppressWarnings("ConstantValue") @@ -170,9 +176,10 @@ void shouldClose_Selector() throws IOException { @Test void shouldClose_Selector_WhenThrowsOnClose() throws IOException { - var socket = mock(Selector.class); - doThrow(new IOException("I cannot select")).when(socket).close(); - assertThatCode(() -> KiwiIO.closeQuietly(socket)).doesNotThrowAnyException(); + var selector = mock(Selector.class); + doThrow(new IOException("I cannot select")).when(selector).close(); + assertThatCode(() -> KiwiIO.closeQuietly(selector)).doesNotThrowAnyException(); + verify(selector).close(); } @SuppressWarnings("ConstantValue") @@ -194,6 +201,7 @@ void shouldClose_ServerSocket_WhenThrowsOnClose() throws IOException { var serverSocket = mock(ServerSocket.class); doThrow(new IOException("I cannot read")).when(serverSocket).close(); assertThatCode(() -> KiwiIO.closeQuietly(serverSocket)).doesNotThrowAnyException(); + verify(serverSocket).close(); } @SuppressWarnings("ConstantValue") @@ -235,6 +243,10 @@ void shouldClose_Closeables_WhenThrowOnClose() throws IOException { doThrow(new IOException("I cannot read")).when(serverSocket).close(); assertThatCode(() -> KiwiIO.closeQuietly(socket, selector, serverSocket)).doesNotThrowAnyException(); + + verify(socket).close(); + verify(selector).close(); + verify(serverSocket).close(); } @SuppressWarnings("ConstantValue") @@ -255,6 +267,7 @@ void shouldClose_XMLStreamReader_WhenThrowsOnClose() throws XMLStreamException { var xmlStreamReader = mock(XMLStreamReader.class); doThrow(new XMLStreamException("I cannot stream XML")).when(xmlStreamReader).close(); assertThatCode(() -> KiwiIO.closeQuietly(xmlStreamReader)).doesNotThrowAnyException(); + verify(xmlStreamReader).close(); } @SuppressWarnings("ConstantValue") @@ -266,8 +279,10 @@ void shouldClose_NullXMLStreamWriter() { @Test void shouldClose_XMLStreamWriter() throws XMLStreamException { - var xmlStreamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(new StringWriter()); + var xmlStreamWriter = mock(XMLStreamWriter.class); + doNothing().when(xmlStreamWriter).close(); assertThatCode(() -> KiwiIO.closeQuietly(xmlStreamWriter)).doesNotThrowAnyException(); + verify(xmlStreamWriter).close(); } @Test @@ -275,6 +290,7 @@ void shouldClose_XMLStreamWriter_WhenThrowsOnClose() throws XMLStreamException { var xmlStreamWriter = mock(XMLStreamWriter.class); doThrow(new XMLStreamException("I cannot stream XML")).when(xmlStreamWriter).close(); assertThatCode(() -> KiwiIO.closeQuietly(xmlStreamWriter)).doesNotThrowAnyException(); + verify(xmlStreamWriter).close(); } } @@ -406,6 +422,19 @@ void shouldCloseManyObjects_WithSameCloseMethodName() { ); } + @Test + void shouldNotAllow_CloseableResource_WhenGivenExplicit_CloseMethodName() { + var halter1 = new Halter(); + var halter2 = new Halter(); + var terminator = new Terminator(); + var terminatorResource = new CloseableResource(terminator, "terminate"); + + var closeMethodName = "halt"; + assertThatIllegalArgumentException() + .isThrownBy(() -> KiwiIO.closeObjectsQuietly(closeMethodName, halter1, halter2, terminatorResource)) + .withMessage("objects should not contain any instances of CloseableResource when a single closeMethodName (%s) is specified", closeMethodName); + } + @Test void shouldCloseManyObjects_WithDifferingCloseMethodName() { var closer = new Closer();