From 929804611a6454afce1860fff6ab895c3b4d23eb Mon Sep 17 00:00:00 2001 From: Aaron Davis Date: Fri, 5 Jan 2018 06:02:09 -0800 Subject: [PATCH] Removing the IllegalStateException types and updating the assertions to use the built in expected/actual fields for better tool support --- README.md | 4 +- pom.xml | 6 +- .../AbortedFailedValidationExecutor.java | 46 ++++++ ...tackTrimmingFailedValidationExecutor.java} | 63 +++----- .../AssertionFailedValidationExecutor.java | 45 ++++++ src/main/java/com/redfin/insist/Insist.java | 20 +-- .../insist/InsistVerifiableFactory.java | 4 +- .../external_package/StackTrimmingTest.java | 2 - .../AbortedFailedValidationExecutorTest.java | 39 +++++ ...kTrimmingFailedValidationExecutorTest.java | 46 ++++++ ...AssertionFailedValidationExecutorTest.java | 39 +++++ .../java/com/redfin/insist/InsistTest.java | 16 --- .../insist/InsistVerifiableFactoryTest.java | 4 +- ...mmingFailedValidationExecutorContract.java | 89 ++++++++++++ ...kTrimmingFailedValidationExecutorTest.java | 134 ------------------ 15 files changed, 335 insertions(+), 222 deletions(-) create mode 100644 src/main/java/com/redfin/insist/AbortedFailedValidationExecutor.java rename src/main/java/com/redfin/insist/{StackTrimmingFailedValidationExecutor.java => AbstractStackTrimmingFailedValidationExecutor.java} (50%) create mode 100644 src/main/java/com/redfin/insist/AssertionFailedValidationExecutor.java create mode 100644 src/test/java/com/redfin/insist/AbortedFailedValidationExecutorTest.java create mode 100644 src/test/java/com/redfin/insist/AbstractStackTrimmingFailedValidationExecutorTest.java create mode 100644 src/test/java/com/redfin/insist/AssertionFailedValidationExecutorTest.java create mode 100644 src/test/java/com/redfin/insist/StackTrimmingFailedValidationExecutorContract.java delete mode 100644 src/test/java/com/redfin/insist/StackTrimmingFailedValidationExecutorTest.java diff --git a/README.md b/README.md index 97ced41..2fa351c 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ To install, you can simply include the dependency from Maven Central: com.redfin insist - 3.0.1 + 4.0.0 ``` @@ -102,3 +102,5 @@ until either a `true` value is received or until the Duration of 1 minute is rea is reached than an assertion failure is thrown. Note that it might stop before 1 minute has been reached if it had a failed attempt and waiting for 500 milliseconds would put it after the requested timeout as per the Patience library. +Also note that it does not interrupt the retrieval of a boolean from the `thatEventually(BooleanSupplier)` so +if the code you are checking hangs it will hang as well or could take longer than the given duration and be successful. diff --git a/pom.xml b/pom.xml index 3504dd9..0e599cb 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.redfin insist - 3.0.1 + 4.0.0 4.0.0 jar @@ -76,12 +76,12 @@ com.redfin validity - 5.0.0 + 5.1.0 com.redfin patience - 3.5.0 + 3.6.0 org.opentest4j diff --git a/src/main/java/com/redfin/insist/AbortedFailedValidationExecutor.java b/src/main/java/com/redfin/insist/AbortedFailedValidationExecutor.java new file mode 100644 index 0000000..d7f31ce --- /dev/null +++ b/src/main/java/com/redfin/insist/AbortedFailedValidationExecutor.java @@ -0,0 +1,46 @@ +/* + * Copyright: (c) 2016 Redfin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.redfin.insist; + +import com.redfin.validity.ValidityUtils; +import org.opentest4j.TestAbortedException; + +/** + * Concrete subclass of the {@link AbstractStackTrimmingFailedValidationExecutor} that + * throws {@link TestAbortedException} exceptions upon failure. + */ +public final class AbortedFailedValidationExecutor + extends AbstractStackTrimmingFailedValidationExecutor { + + @Override + protected String getDefaultMessage() { + return "Test aborted"; + } + + @Override + protected TestAbortedException buildThrowable(String expected, + T actual, + String message) { + if (null == expected) { + throw new NullPointerException(ValidityUtils.nullArgumentMessage("expected")); + } + return new TestAbortedException(String.format("%s\n expected : %s\n actual : <%s>", + message, + expected, + ValidityUtils.describe(actual))); + } +} diff --git a/src/main/java/com/redfin/insist/StackTrimmingFailedValidationExecutor.java b/src/main/java/com/redfin/insist/AbstractStackTrimmingFailedValidationExecutor.java similarity index 50% rename from src/main/java/com/redfin/insist/StackTrimmingFailedValidationExecutor.java rename to src/main/java/com/redfin/insist/AbstractStackTrimmingFailedValidationExecutor.java index 32d04df..da1cfdc 100644 --- a/src/main/java/com/redfin/insist/StackTrimmingFailedValidationExecutor.java +++ b/src/main/java/com/redfin/insist/AbstractStackTrimmingFailedValidationExecutor.java @@ -21,73 +21,42 @@ import com.redfin.validity.ValidityUtils; import java.util.OptionalInt; -import java.util.function.Function; import java.util.function.Supplier; -import static com.redfin.validity.Validity.validate; - /** - * An implementation of {@link FailedValidationExecutor} thatEventually will remove all stack frames - * from the generated {@link Throwable} except for the actual line thatEventually called for validation. - * This is intended for use with Assertions and Assumptions thatEventually will be used in actual test methods - * where the extended stack frame is noisy and not helpful. It should not be used in frameworks or - * production code where the stack trace is essential for debugging. + * Base class for {@link FailedValidationExecutor} instances that will be trimming out all except for the first + * non-Insist, non-Validity libraries line from the stack trace. + * + * @param the type of the Throwable it will throw. */ -final class StackTrimmingFailedValidationExecutor - implements FailedValidationExecutor { - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Constants - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +public abstract class AbstractStackTrimmingFailedValidationExecutor + implements FailedValidationExecutor { - private static final String DEFAULT_MESSAGE = "Insistence failure"; - private static final String MESSAGE_FORMAT = "%s\n expected : %s\n subject : <%s>"; - private static final String PACKAGE_NAME = StackTrimmingFailedValidationExecutor.class.getPackage().getName() + "."; + private static final String PACKAGE_NAME = AssertionFailedValidationExecutor.class.getPackage().getName() + "."; private static final String VALIDITY_PACKAGE_NAME = Validity.class.getPackage().getName() + "."; - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Members - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + protected abstract String getDefaultMessage(); - private final Function throwableFunction; - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Instance Methods - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - /** - * Create a new instance of a {@link StackTrimmingFailedValidationExecutor} thatEventually - * will use the given throwableFunction when the {@link #fail(String, Object, Supplier)} - * method is called. - * - * @param throwableFunction the {@link Function} thatEventually takes in a String and returns a - * Throwable of type X. - * May not be null. - * Should never return a null Throwable. - * - * @throws IllegalArgumentException if throwableFunction is null. - */ - StackTrimmingFailedValidationExecutor(Function throwableFunction) { - this.throwableFunction = validate().that(throwableFunction).isNotNull(); - } + protected abstract X buildThrowable(String expected, + T actual, + String message); @Override - public void fail(String expected, - T subject, - Supplier messageSupplier) throws X { + public final void fail(String expected, + T actual, + Supplier messageSupplier) throws X { if (null == expected) { throw new NullPointerException(ValidityUtils.nullArgumentMessage("expected")); } if (null == messageSupplier) { throw new NullPointerException(ValidityUtils.nullArgumentMessage("messageSupplier")); } - String subjectDescription = ValidityUtils.describe(subject); String message = messageSupplier.get(); if (null == message) { - message = DEFAULT_MESSAGE; + message = getDefaultMessage(); } // Create the throwable - X throwable = throwableFunction.apply(String.format(MESSAGE_FORMAT, message, expected, subjectDescription)); + X throwable = buildThrowable(expected, actual, message); if (null == throwable) { throw new NullPointerException(ValidityUtils.nullThrowableFromFunction()); } diff --git a/src/main/java/com/redfin/insist/AssertionFailedValidationExecutor.java b/src/main/java/com/redfin/insist/AssertionFailedValidationExecutor.java new file mode 100644 index 0000000..26c4ede --- /dev/null +++ b/src/main/java/com/redfin/insist/AssertionFailedValidationExecutor.java @@ -0,0 +1,45 @@ +/* + * Copyright: (c) 2016 Redfin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.redfin.insist; + +import com.redfin.validity.ValidityUtils; +import org.opentest4j.AssertionFailedError; + +/** + * Concrete subclass of the {@link AbstractStackTrimmingFailedValidationExecutor} that + * throws {@link AssertionFailedError} errors upon failure. + */ +public final class AssertionFailedValidationExecutor + extends AbstractStackTrimmingFailedValidationExecutor { + + @Override + protected String getDefaultMessage() { + return "Assertion failure"; + } + + @Override + protected AssertionFailedError buildThrowable(String expected, + T actual, + String message) { + if (null == expected) { + throw new NullPointerException(ValidityUtils.nullArgumentMessage("expected")); + } + return new AssertionFailedError(message, + expected, + actual); + } +} diff --git a/src/main/java/com/redfin/insist/Insist.java b/src/main/java/com/redfin/insist/Insist.java index 62b826a..7c4f46c 100644 --- a/src/main/java/com/redfin/insist/Insist.java +++ b/src/main/java/com/redfin/insist/Insist.java @@ -29,9 +29,8 @@ public final class Insist { // Constants // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - private static final StackTrimmingFailedValidationExecutor ASSERT_EXECUTOR; - private static final StackTrimmingFailedValidationExecutor ASSUME_EXECUTOR; - private static final StackTrimmingFailedValidationExecutor EXPECT_EXECUTOR; + private static final AssertionFailedValidationExecutor ASSERT_EXECUTOR; + private static final AbortedFailedValidationExecutor ASSUME_EXECUTOR; /* * The null message instances of the factories can be re-used safely. Cache them @@ -40,15 +39,12 @@ public final class Insist { private static final InsistVerifiableFactory NULL_MESSAGE_ASSERT_FACTORY; private static final InsistVerifiableFactory NULL_MESSAGE_ASSUME_FACTORY; - private static final InsistVerifiableFactory NULL_MESSAGE_EXPECT_FACTORY; static { - ASSERT_EXECUTOR = new StackTrimmingFailedValidationExecutor<>(AssertionFailedError::new); - ASSUME_EXECUTOR = new StackTrimmingFailedValidationExecutor<>(TestAbortedException::new); - EXPECT_EXECUTOR = new StackTrimmingFailedValidationExecutor<>(IllegalStateException::new); + ASSERT_EXECUTOR = new AssertionFailedValidationExecutor(); + ASSUME_EXECUTOR = new AbortedFailedValidationExecutor(); NULL_MESSAGE_ASSERT_FACTORY = new InsistVerifiableFactory<>(() -> null, ASSERT_EXECUTOR); NULL_MESSAGE_ASSUME_FACTORY = new InsistVerifiableFactory<>(() -> null, ASSUME_EXECUTOR); - NULL_MESSAGE_EXPECT_FACTORY = new InsistVerifiableFactory<>(() -> null, EXPECT_EXECUTOR); } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -71,14 +67,6 @@ public static InsistVerifiableFactory assumes() { return NULL_MESSAGE_ASSUME_FACTORY; } - /** - * @return an {@link InsistVerifiableFactory} instance with the default message prefix thatEventually - * throws an {@link IllegalStateException} on validation failure. - */ - public static InsistVerifiableFactory expects() { - return NULL_MESSAGE_EXPECT_FACTORY; - } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Instance Methods // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/main/java/com/redfin/insist/InsistVerifiableFactory.java b/src/main/java/com/redfin/insist/InsistVerifiableFactory.java index 0edda78..bd6b8b9 100644 --- a/src/main/java/com/redfin/insist/InsistVerifiableFactory.java +++ b/src/main/java/com/redfin/insist/InsistVerifiableFactory.java @@ -94,7 +94,9 @@ public InsistCompletableFuture withWait(PatientWait wait) { /** * Like calling {@link #withWait(PatientWait)} with a wait object that retries * repeatedly up to the set tryingFor maximum with a short delay between - * attempts. Any throwable thrown during the execution will be ignored. + * attempts. Any throwable thrown during the execution will be ignored. Note that this + * does NOT interrupt the attempt to get a valid result but checks the timeout between + * successive attempts to get a true value. * * @param tryingFor the {@link Duration} object to be used as the maximum * time to wait. diff --git a/src/test/java/com/redfin/external_package/StackTrimmingTest.java b/src/test/java/com/redfin/external_package/StackTrimmingTest.java index 5069f74..d5caefa 100644 --- a/src/test/java/com/redfin/external_package/StackTrimmingTest.java +++ b/src/test/java/com/redfin/external_package/StackTrimmingTest.java @@ -22,8 +22,6 @@ import org.junit.jupiter.api.Test; import org.opentest4j.AssertionFailedError; -import java.time.Duration; - /* * A separate package is used for this test since the default behavior * of the DefaultValidityFailedValidationExecutor supplied in the library diff --git a/src/test/java/com/redfin/insist/AbortedFailedValidationExecutorTest.java b/src/test/java/com/redfin/insist/AbortedFailedValidationExecutorTest.java new file mode 100644 index 0000000..df3414e --- /dev/null +++ b/src/test/java/com/redfin/insist/AbortedFailedValidationExecutorTest.java @@ -0,0 +1,39 @@ +/* + * Copyright: (c) 2016 Redfin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.redfin.insist; + +import com.redfin.validity.FailedValidationExecutor; +import org.opentest4j.TestAbortedException; + +final class AbortedFailedValidationExecutorTest + implements StackTrimmingFailedValidationExecutorContract { + + @Override + public AbortedFailedValidationExecutor getStackTrimmingFailedValidationExecutor() { + return new AbortedFailedValidationExecutor(); + } + + @Override + public FailedValidationExecutor getFailedValidationExecutor() { + return getStackTrimmingFailedValidationExecutor(); + } + + @Override + public Class getThrowableClass() { + return TestAbortedException.class; + } +} diff --git a/src/test/java/com/redfin/insist/AbstractStackTrimmingFailedValidationExecutorTest.java b/src/test/java/com/redfin/insist/AbstractStackTrimmingFailedValidationExecutorTest.java new file mode 100644 index 0000000..2796062 --- /dev/null +++ b/src/test/java/com/redfin/insist/AbstractStackTrimmingFailedValidationExecutorTest.java @@ -0,0 +1,46 @@ +/* + * Copyright: (c) 2016 Redfin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.redfin.insist; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +final class AbstractStackTrimmingFailedValidationExecutorTest { + + private static class MockImplementation + extends AbstractStackTrimmingFailedValidationExecutor { + + @Override + protected String getDefaultMessage() { + return "hello"; + } + + @Override + protected IllegalArgumentException buildThrowable(String expected, + T actual, + String message) { + return null; + } + } + + @Test + void testFailThrowsForNullThrowableReturnedbySubclass() { + Assertions.assertThrows(NullPointerException.class, + () -> new MockImplementation().fail("t -> t.equals(\"hello\")", "world", () -> "default message"), + "AbstractStackTrimmingFailedValidationExecutor should throw an exception if buildThrowable returns a null throwable."); + } +} diff --git a/src/test/java/com/redfin/insist/AssertionFailedValidationExecutorTest.java b/src/test/java/com/redfin/insist/AssertionFailedValidationExecutorTest.java new file mode 100644 index 0000000..4dc990d --- /dev/null +++ b/src/test/java/com/redfin/insist/AssertionFailedValidationExecutorTest.java @@ -0,0 +1,39 @@ +/* + * Copyright: (c) 2016 Redfin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.redfin.insist; + +import com.redfin.validity.FailedValidationExecutor; +import org.opentest4j.AssertionFailedError; + +final class AssertionFailedValidationExecutorTest + implements StackTrimmingFailedValidationExecutorContract { + + @Override + public AssertionFailedValidationExecutor getStackTrimmingFailedValidationExecutor() { + return new AssertionFailedValidationExecutor(); + } + + @Override + public FailedValidationExecutor getFailedValidationExecutor() { + return getStackTrimmingFailedValidationExecutor(); + } + + @Override + public Class getThrowableClass() { + return AssertionFailedError.class; + } +} diff --git a/src/test/java/com/redfin/insist/InsistTest.java b/src/test/java/com/redfin/insist/InsistTest.java index 3cca4dc..4aa7740 100644 --- a/src/test/java/com/redfin/insist/InsistTest.java +++ b/src/test/java/com/redfin/insist/InsistTest.java @@ -71,22 +71,6 @@ void testInsistAssertsReturnsNullMessageFactory() throws Exception { "Insist.asserts() should return a factory with a null message."); } - @Test - void testInsistExpectsReturnsNonNullFactory() { - Assertions.assertNotNull(Insist.expects(), - "Insist.expects() should return a non-null factory."); - } - - @Test - @SuppressWarnings("unchecked") - void testInsistExpectsReturnsNullMessageFactory() throws Exception { - AbstractVerifiableFactory factory = Insist.expects(); - Field field = factory.getClass().getSuperclass().getDeclaredField("messageSupplier"); - field.setAccessible(true); - Assertions.assertNull(((Supplier) field.get(factory)).get(), - "Insist.expects() should return a factory with a null message."); - } - @Test void testInsistIsMarkedAsFinal() { Assertions.assertTrue(Modifier.isFinal(Insist.class.getModifiers()), diff --git a/src/test/java/com/redfin/insist/InsistVerifiableFactoryTest.java b/src/test/java/com/redfin/insist/InsistVerifiableFactoryTest.java index d5a0108..b83ec28 100644 --- a/src/test/java/com/redfin/insist/InsistVerifiableFactoryTest.java +++ b/src/test/java/com/redfin/insist/InsistVerifiableFactoryTest.java @@ -32,7 +32,7 @@ final class InsistVerifiableFactoryTest { // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ private InsistVerifiableFactory getInstance(Supplier messageSupplier) { - return getInstance(messageSupplier, new StackTrimmingFailedValidationExecutor<>(AssertionFailedError::new)); + return getInstance(messageSupplier, new AssertionFailedValidationExecutor()); } private InsistVerifiableFactory getInstance(Supplier messageSupplier, @@ -68,7 +68,7 @@ void testConstructorThrowsExceptionForNullFailedValidationExecutor() { @Test void testGetFactoryReturnsANonNullInstance() { Assertions.assertNotNull(getInstance(() -> "message").getFactory(() -> "newMessage", - new StackTrimmingFailedValidationExecutor<>(AssertionFailedError::new)), + new AssertionFailedValidationExecutor()), "InsistVerifiableFactory getFactory should return a non-null instance."); } diff --git a/src/test/java/com/redfin/insist/StackTrimmingFailedValidationExecutorContract.java b/src/test/java/com/redfin/insist/StackTrimmingFailedValidationExecutorContract.java new file mode 100644 index 0000000..b022d85 --- /dev/null +++ b/src/test/java/com/redfin/insist/StackTrimmingFailedValidationExecutorContract.java @@ -0,0 +1,89 @@ +/* + * Copyright: (c) 2016 Redfin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.redfin.insist; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * A unit test contract for implementing sub-classes of the {@link AbstractStackTrimmingFailedValidationExecutor} type. + * + * @param the type of the throwable thrown by the sub class. + * @param the type of the stack trimming failed validation executor to be tested. + */ +interface StackTrimmingFailedValidationExecutorContract> + extends FailedValidationExecutorContract { + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Test contract requirements + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + /** + * @return an instance of the type under test. + */ + F getStackTrimmingFailedValidationExecutor(); + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Test cases + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Test + default void testCanInstantiate() { + Assertions.assertNotNull(getStackTrimmingFailedValidationExecutor(), + "Should be able to instantiate an instance of the type under test."); + } + + @Test + default void testReturnsNonNullDefaultMessage() { + Assertions.assertNotNull(getStackTrimmingFailedValidationExecutor().getDefaultMessage(), + "Should return a non-null default message."); + } + + @Test + default void testBuildThrowableReturnsNonNullForValidValues() { + Assertions.assertNotNull(getStackTrimmingFailedValidationExecutor().buildThrowable("t -> null != t", + "hello", + "message time"), + "Failed validation executor should return a non-null throwable for valid values to buildThrowable."); + } + + @Test + default void testBuildThrowableReturnsNonNullForNullActual() { + Assertions.assertNotNull(getStackTrimmingFailedValidationExecutor().buildThrowable("t -> null != t", + null, + "message time"), + "Failed validation executor should return a non-null throwable for valid values to buildThrowable."); + } + + @Test + default void testBuildThrowableReturnsNonNullForNullMessage() { + Assertions.assertNotNull(getStackTrimmingFailedValidationExecutor().buildThrowable("t -> null != t", + "hello", + null), + "Failed validation executor should return a non-null throwable for valid values to buildThrowable."); + } + + @Test + default void testBuildThrowableThrowsForNullExpected() { + Assertions.assertThrows(NullPointerException.class, + () -> getStackTrimmingFailedValidationExecutor().buildThrowable(null, + "hello", + "message time"), + "Failed validation executor should throw for a non expected to buildThrowable."); + } +} diff --git a/src/test/java/com/redfin/insist/StackTrimmingFailedValidationExecutorTest.java b/src/test/java/com/redfin/insist/StackTrimmingFailedValidationExecutorTest.java deleted file mode 100644 index be0ff11..0000000 --- a/src/test/java/com/redfin/insist/StackTrimmingFailedValidationExecutorTest.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright: (c) 2016 Redfin - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.redfin.insist; - -import com.redfin.validity.DefaultValidityFailedValidationExecutor; -import com.redfin.validity.FailedValidationExecutor; -import com.redfin.validity.ValidityUtils; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -final class StackTrimmingFailedValidationExecutorTest { - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Test values & contract implementations - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - interface ValidationExecutorsMessageContract extends FailedValidationExecutorContract { - - String MESSAGE_FORMAT = "%s\n expected : %s\n subject : <%s>"; - - @Test - default void testThrownExceptionHasExpectedMessage() { - String expected = "expected"; - String subject = "subject"; - String message = "message"; - X throwable = Assertions.assertThrows(getThrowableClass(), - () -> getFailedValidationExecutor().fail(expected, subject, () -> message)); - Assertions.assertEquals(String.format(MESSAGE_FORMAT, - message, - expected, - subject), - throwable.getMessage(), - "The failed validation executors for the validity library should have the expected message."); - } - - @Test - default void testThrownExceptionHasExpectedMessageWithNullMessage() { - String expected = "expected"; - String subject = "subject"; - X throwable = Assertions.assertThrows(getThrowableClass(), - () -> getFailedValidationExecutor().fail(expected, subject, () -> null)); - Assertions.assertTrue(null != throwable.getMessage() && throwable.getMessage().startsWith("Insistence failure"), - "Expected the thrown throwable for validation failure to start with the expected message."); - } - - @Test - default void testFailedValidationExecutorThrowsForNullThrowable() { - FailedValidationExecutor executor = new StackTrimmingFailedValidationExecutor<>(message -> null); - Assertions.assertThrows(NullPointerException.class, - () -> executor.fail("expected", "subject", () -> "message")); - } - } - - interface NoStackTraceValidationExecutorsContract extends ValidationExecutorsMessageContract { - - final class NoStackRuntimeException extends RuntimeException { - NoStackRuntimeException(String message) { - super(message); - } - - @Override - public StackTraceElement[] getStackTrace() { - return null; - } - } - - FailedValidationExecutor getNoStackFailedValidationExecutor(); - - @Test - default void testValidationExecutorCanHandleEmptyStackTraceFromException() { - String expected = "expected"; - String subject = "subject"; - String message = "message"; - Assertions.assertThrows(NoStackRuntimeException.class, - () -> getNoStackFailedValidationExecutor().fail(expected, subject, () -> message)); - } - } - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Test containers - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - @Nested - final class StackTrimmingFailedValidationExecutorTestContainer implements NoStackTraceValidationExecutorsContract { - - @Override - public FailedValidationExecutor getFailedValidationExecutor() { - return new StackTrimmingFailedValidationExecutor<>(IllegalStateException::new); - } - - @Override - public Class getThrowableClass() { - return IllegalStateException.class; - } - - @Override - public FailedValidationExecutor getNoStackFailedValidationExecutor() { - return new StackTrimmingFailedValidationExecutor<>(NoStackRuntimeException::new); - } - - @Test - void throwsExceptionForNullThrowableFunction() { - NullPointerException exception = Assertions.assertThrows(NullPointerException.class, - () -> new DefaultValidityFailedValidationExecutor<>(null)); - Assertions.assertEquals(ValidityUtils.nullArgumentMessage("throwableFunction"), - exception.getMessage(), - "Failed validation executors should throw an exception for a null throwable function."); - } - - @Test - void testFailedValidationExecutorThrowsExceptionForNullThrowableCreation() { - NullPointerException exception = Assertions.assertThrows(NullPointerException.class, - () -> new DefaultValidityFailedValidationExecutor<>(str -> null).fail("", "", () -> "")); - Assertions.assertEquals(ValidityUtils.nullThrowableFromFunction(), - exception.getMessage(), - "Failed validation executors should throw the expected exception for a null throwable created."); - } - } -}