/** * Assert that the given class adheres to the immutable class rules. * * @param clazz the class to check * * @throws java.lang.AssertionError if the class is not an * immutable class */ public static void assertThatClassIsImmutable(Class<?> clazz) { final ImmutableClassChecker checker = new ImmutableClassChecker(); if (!checker.isImmutableClass(clazz, false)) { final Description toDescription = new StringDescription(); final Description mismatchDescription = new StringDescription(); checker.describeTo(toDescription); checker.describeMismatch(mismatchDescription); final String reason = "\n" + "Expected: is \"" + toDescription.toString() + "\"\n" + " but : was \"" + mismatchDescription.toString() + "\""; throw new AssertionError(reason); } }
/** * Assert that the given class adheres to the immutable class rules, but * is not declared final. Classes that need to be inherited from cannot be * declared final. * * @param clazz the class to check * * @throws java.lang.AssertionError if the class is not an * immutable class */ public static void assertThatClassIsImmutableBaseClass(Class<?> clazz) { final ImmutableClassChecker checker = new ImmutableClassChecker(); if (!checker.isImmutableClass(clazz, true)) { final Description toDescription = new StringDescription(); final Description mismatchDescription = new StringDescription(); checker.describeTo(toDescription); checker.describeMismatch(mismatchDescription); final String reason = "\n" + "Expected: is \"" + toDescription.toString() + "\"\n" + " but : was \"" + mismatchDescription.toString() + "\""; throw new AssertionError(reason); } }
/** * Assert that the given class adheres to the utility class rules. * * @param clazz the class to check * * @throws java.lang.AssertionError if the class is not a valid * utility class */ public static void assertThatClassIsUtility(Class<?> clazz) { final UtilityClassChecker checker = new UtilityClassChecker(); if (!checker.isProperlyDefinedUtilityClass(clazz)) { final Description toDescription = new StringDescription(); final Description mismatchDescription = new StringDescription(); checker.describeTo(toDescription); checker.describeMismatch(mismatchDescription); final String reason = "\n" + "Expected: is \"" + toDescription.toString() + "\"\n" + " but : was \"" + mismatchDescription.toString() + "\""; throw new AssertionError(reason); } }
@Override public void describeTo(Description description) { description.appendText("{\n"); _entryMatchers.forEach( (key, matcher) -> { description.appendText(" "); description.appendText(key); description.appendText(": "); Description innerDescription = new StringDescription(); matcher.describeTo(innerDescription); indentDescription(description, innerDescription); }); description.appendText("}"); }
@Test public void testInvokingDescribesToUpdatesDescription() { Conditions.Builder builder = new Conditions.Builder(); Conditions conditions = builder.where( "apio", is(aJsonString(equalTo("Live long and prosper"))) ).where( "geek", is(aJsonBoolean(true)) ).build(); Description description = new StringDescription(); conditions.describeTo(description); String expected = "a JSON object where {\n apio: is a string element with a value " + "that is \"Live long and prosper\"\n geek: is a boolean " + "element with a value that is <true>\n}"; assertThat(description.toString(), is(expected)); }
@Test public void testInvokingMatchesElementInSoftModeValidates() { Conditions.Builder builder = new Conditions.Builder(); Conditions conditions = builder.where( "geek", is(aJsonBoolean(true)) ).where( "apio", is(aJsonString(equalTo("Live long and prosper"))) ).withStrictModeDeactivated( ).build(); Description description = new StringDescription(); JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("geek", true); jsonObject.addProperty("number", 42); jsonObject.addProperty("other", "apio"); jsonObject.addProperty("apio", "Live long and prosper"); boolean matchesElement = conditions.matches(jsonObject); conditions.describeMismatch(jsonObject, description); assertThat(matchesElement, is(true)); }
@Test public void testInvalidJsonObjectWithMultiConditionUpdatesDescription() { Conditions conditions = _builder.where( "apio", is(aJsonString(equalTo("Live long and prosper"))) ).where( "geek", is(aJsonBoolean(true)) ).build(); Matcher<String> stringMatcher = aJsonObjectStringWith(conditions); Description description = new StringDescription(); stringMatcher.describeMismatch("{}", description); String expected = "was a JSON object {\n apio: was null\n geek: was null\n}"; assertThat(description.toString(), is(expected)); }
public static <T> boolean verifyThat(String reason, T actual, Matcher<? super T> matcher) { boolean result = matcher.matches(actual); Description description = new StringDescription(); description.appendText(reason).appendText("\nExpected: ").appendDescriptionOf(matcher) .appendText("\n Actual: "); matcher.describeMismatch(actual, description); String msg = description.toString(); if (msg.endsWith("Actual: ")) { msg = String.format(msg + "%s", actual); } msg = msg.replaceAll("<", "<").replaceAll(">", ">"); Reporter.log(msg, result ? MessageTypes.Pass : MessageTypes.Fail); return result; }
/** * Matches that the given <code>TokenStream</code> produces the expected sequence of tokens. Fails if a token does * not match its respective matcher, or if the number of tokens in the token stream does not match the number of * given matchers. * * @param stream * the token stream. * @param expectedTokens * the matchers for the expected tokens. */ @SafeVarargs protected final void assertTokenStream(TokenStream stream, Matcher<TokenStream>... expectedTokens) throws Exception { final int expectedTokenCount = expectedTokens.length; int tokenCount = 0; while (stream.incrementToken()) { assertTrue("Too many tokens", tokenCount < expectedTokens.length); Matcher<TokenStream> tokenMatcher = expectedTokens[tokenCount]; boolean matches = tokenMatcher.matches(stream); if (!matches) { Description description = new StringDescription(); description.appendText("Unexpected token at position ").appendValue(tokenCount).appendText("\n"); tokenMatcher.describeMismatch(stream, description); fail(description.toString()); } tokenCount++; } assertEquals("Unexpected number of tokens", expectedTokenCount, tokenCount); }
@Test public void describeNestedMismatchesNoEllipsisBeforeFirstValue() throws Exception { Set<String> allKeys = new LinkedHashSet<>(asList("first", "second", "third")); StringDescription description = new StringDescription(); Map<String, Consumer<Description>> mismatchedKeys = ImmutableMap.of("first", desc -> desc.appendText("mismatch!")); BiConsumer<String, Description> describeKey = (str, desc) -> desc.appendText(str); DescriptionUtils.describeNestedMismatches(allKeys, description, mismatchedKeys, describeKey); assertThat(description.toString(), is( "{\n" + " first: mismatch!\n" + " ...\n" + "}" )); }
@Test public void testOffset() throws Exception { Description description = mock(Description.class); when(description.appendText(anyString())).thenReturn(description); when(description.appendValue(anyInt())).thenReturn(description); Matcher<TokenStream> offsetsMatcher = test.offsets(0, 1); offsetsMatcher.describeTo(description); verify(description, times(1)).appendText("startOffset="); verify(description, times(1)).appendValue(0); verify(description, times(1)).appendText(",endOffset="); verify(description, times(1)).appendValue(1); // Not a real test, but good for coverage assertFalse(test.offsets(42, 4711).matches(stream)); test.offsets(42, 4711).describeMismatch(stream, new StringDescription()); }
@Test public void testDescriptionFormatting() throws Exception { final IsPojo<SomeClass> sut = pojo(SomeClass.class) .where("baz", is(pojo(SomeClass.class).where("foo", is(42)))) .where("foo", is(42)) .withProperty("bar", is("bar")); final StringDescription description = new StringDescription(); sut.describeTo(description); assertThat(description.toString(), is( "SomeClass {\n" + " baz(): is SomeClass {\n" + " foo(): is <42>\n" + " }\n" + " foo(): is <42>\n" + " getBar(): is \"bar\"\n" + "}" )); }
@Test public void testMismatchFormatting() throws Exception { final IsPojo<SomeClass> sut = pojo(SomeClass.class) .where("baz", is( pojo(SomeClass.class) .where("foo", is(43)) )) .where("foo", is(42)) .withProperty("bar", is("bar")); final StringDescription description = new StringDescription(); sut.describeMismatch(new SomeClass(), description); assertThat(description.toString(), is( "SomeClass {\n" + " baz(): SomeClass {\n" + " foo(): was <42>\n" + " }\n" + " ...\n" + "}" )); }
@Test public void describeNestMismatchesNoEllipsisBetweenConsecutiveMismatches() throws Exception { Set<String> allKeys = new LinkedHashSet<>(asList("first", "second", "third", "forth")); StringDescription description = new StringDescription(); Map<String, Consumer<Description>> mismatchedKeys = ImmutableMap.of( "second", desc -> desc.appendText("mismatch!"), "third", desc -> desc.appendText("mismatch!")); BiConsumer<String, Description> describeKey = (str, desc) -> desc.appendText(str); DescriptionUtils.describeNestedMismatches(allKeys, description, mismatchedKeys, describeKey); assertThat(description.toString(), is( "{\n" + " ...\n" + " second: mismatch!\n" + " third: mismatch!\n" + " ...\n" + "}" )); }
@Test public void testTypeSafeMismatch() throws Exception { final IsPojo<SomeClass> sut = pojo(SomeClass.class) .where(SomeClass::foo, is(41)) .where(SomeClass::baz, is( pojo(SomeClass.class) .where(SomeClass::foo, is(43)) )); final StringDescription description = new StringDescription(); sut.describeMismatch(new SomeClass(), description); assertThat(description.toString(), is( "SomeClass {\n" + " foo(): was <42>\n" + " baz(): SomeClass {\n" + " foo(): was <42>\n" + " }\n" + "}" )); }
@Test public void testInterruptedMismatchFormatting() throws Exception { final CompletableFuture<Void> future = runAsync(waitUntilInterrupted()); try { // Interrupt this current thread so that future.get() will throw InterruptedException Thread.currentThread().interrupt(); final StringDescription description = new StringDescription(); SUT.describeMismatch(future, description); assertThat(description.toString(), is("a stage that was interrupted")); } finally { // This will cause the future's thread to throw InterruptedException and make it return future.cancel(true); } }
@Test public void testCancelledMismatchFormatting() throws Exception { final SettableFuture<Void> future = SettableFuture.create(); try { // Cancel the future future.cancel(true); final StringDescription description = new StringDescription(); SUT.describeMismatch(future, description); assertThat(description.toString(), is("a future that was cancelled")); } finally { // This will cause the future's thread to throw InterruptedException and make it return future.cancel(true); } }
@Test public void testInterruptedMismatchFormatting() throws Exception { final SettableFuture<Void> future = SettableFuture.create(); try { // Interrupt this current thread so that future.get() will throw InterruptedException Thread.currentThread().interrupt(); final StringDescription description = new StringDescription(); SUT.describeMismatch(future, description); assertThat(description.toString(), is("a future that was not done")); } finally { // This will cause the future's thread to throw InterruptedException and make it return future.cancel(true); } }
@Test public void describeNestedMismatchesProperlyIndentsNestedMismatch() throws Exception { Set<String> allKeys = new LinkedHashSet<>(asList("first", "second", "third")); StringDescription description = new StringDescription(); Map<String, Consumer<Description>> mismatchedKeys = ImmutableMap.of("second", desc -> desc.appendText("{\n nestedKey: mismatch!\n}")); BiConsumer<String, Description> describeKey = (str, desc) -> desc.appendText(str); DescriptionUtils.describeNestedMismatches(allKeys, description, mismatchedKeys, describeKey); assertThat(description.toString(), is( "{\n" + " ...\n" + " second: {\n" + " nestedKey: mismatch!\n" + " }\n" + " ...\n" + "}" )); }
@Test public void testInterruptedMismatchFormatting() throws Exception { final CompletableFuture<Void> future = runAsync(waitUntilInterrupted()); try { // Interrupt this current thread so that future.get() will throw InterruptedException Thread.currentThread().interrupt(); final StringDescription description = new StringDescription(); SUT.describeMismatch(future, description); assertThat(description.toString(), is("a stage that was not done")); } finally { // This will cause the future's thread to throw InterruptedException and make it return future.cancel(true); } }
@Test public void testCancelledMismatchFormatting() throws Exception { final CompletableFuture<Void> future = runAsync(waitUntilInterrupted()); try { // Cancel the future future.cancel(true); final StringDescription description = new StringDescription(); SUT.describeMismatch(future, description); assertThat(description.toString(), is("a stage that was cancelled")); } finally { // This will cause the future's thread to throw InterruptedException and make it return future.cancel(true); } }
@Test public void testInterruptedMismatchFormatting() throws Exception { final SettableFuture<Void> future = SettableFuture.create(); try { // Interrupt this current thread so that future.get() will throw InterruptedException Thread.currentThread().interrupt(); final StringDescription description = new StringDescription(); SUT.describeMismatch(future, description); assertThat(description.toString(), is("a future that was not completed")); } finally { // This will cause the future's thread to throw InterruptedException and make it return future.cancel(true); } }
@Test public void describeMismatchesNoEllipsisAfterLastValue() throws Exception { Set<String> allKeys = new LinkedHashSet<>(asList("first", "second", "third")); StringDescription description = new StringDescription(); Map<String, Consumer<Description>> mismatchedKeys = ImmutableMap.of("third", desc -> desc.appendText("mismatch!")); BiConsumer<String, Description> describeKey = (str, desc) -> desc.appendText(str); DescriptionUtils.describeNestedMismatches(allKeys, description, mismatchedKeys, describeKey); assertThat(description.toString(), is( "{\n" + " ...\n" + " third: mismatch!\n" + "}" )); }
@Test public void testInterruptedMismatchFormatting() throws Exception { final CompletableFuture<Void> future = runAsync(waitUntilInterrupted()); try { // Interrupt this current thread so that future.get() will throw InterruptedException Thread.currentThread().interrupt(); final StringDescription description = new StringDescription(); SUT.describeMismatch(future, description); assertThat(description.toString(), is("a stage that was not completed")); } finally { // This will cause the future's thread to throw InterruptedException and make it return future.cancel(true); } }
@Test public void testInterruptedMismatchFormatting() throws Exception { final SettableFuture<Void> future = SettableFuture.create(); try { // Interrupt this current thread so that future.get() will throw InterruptedException Thread.currentThread().interrupt(); final StringDescription description = new StringDescription(); SUT.describeMismatch(future, description); assertThat(description.toString(), is("a future that was interrupted")); } finally { // This will cause the future's thread to throw InterruptedException and make it return future.cancel(true); } }
@Override public void describeTo(Description description) { description.appendText("{\n"); for (Map.Entry<String, Matcher<? super JsonNode>> entryMatcher : entryMatchers.entrySet()) { final String key = entryMatcher.getKey(); final Matcher<? super JsonNode> valueMatcher = entryMatcher.getValue(); description.appendText(" "); describeKey(key, description); description.appendText(": "); final Description innerDescription = new StringDescription(); valueMatcher.describeTo(innerDescription); DescriptionUtils.indentDescription(description, innerDescription); } description.appendText("}"); }
@Test public void lastNodeMismatchHasNoTrailingEllipsisButHasLeading() throws Exception { final Matcher<JsonNode> sut = jsonObject() .where("foo", is(jsonInt(1))) .where("bar", is(jsonBoolean(false))); final StringDescription description = new StringDescription(); sut.describeMismatch(NF.objectNode().put("foo", 1).put("bar", true), description); assertThat(description.toString(), is( "{\n" + " ...\n" + " \"bar\": was a boolean node with value that was <true>\n" + "}" )); }
@Test public void testMismatchNested() throws Exception { final Matcher<JsonNode> sut = is( jsonObject() .where("foo", is(jsonInt(1))) .where("bar", is(jsonBoolean(true))) .where("baz", is( jsonObject() .where("foo", is(jsonNull()))))); final StringDescription description = new StringDescription(); sut.describeMismatch(NF.objectNode().put("foo", 1).put("bar", true) .set("baz", NF.objectNode().set("foo", NF.booleanNode(false))), description); assertThat(description.toString(), is( "{\n" + " ...\n" + " \"baz\": {\n" + " \"foo\": was not a null node, but a boolean node\n" + " }\n" + "}" )); }
@Test public void multipleConsecutiveMismatchesHaveNoEllipsis() throws Exception { final Matcher<JsonNode> sut = jsonObject() .where("foo", is(jsonInt(1))) .where("bar", is(jsonInt(2))) .where("baz", is(jsonInt(3))); final ObjectNode nestedMismatches = NF.objectNode() .put("foo", -1) .put("bar", "was string") .put("baz", 3); final StringDescription description = new StringDescription(); sut.describeMismatch(nestedMismatches, description); assertThat(description.toString(), is( "{\n" + " \"foo\": was a number node with value that was <-1>\n" + " \"bar\": was not a number node, but a string node\n" + " ...\n" + "}" )); }
@Test public void testMultipleMismatchesWithNestingReportsAllMismatches() throws Exception { final Matcher<JsonNode> sut = jsonObject() .where("foo", is(jsonObject() .where("val", jsonBoolean(true)))) .where("bar", is(jsonInt(2))) .where("baz", is(jsonInt(3))); final ObjectNode nestedMismatches = NF.objectNode() .put("bar", "was string") .put("baz", 3); nestedMismatches.set("foo", NF.objectNode().put("val", false)); final StringDescription description = new StringDescription(); sut.describeMismatch(nestedMismatches, description); assertThat(description.toString(), is( "{\n" + " \"foo\": {\n" + " \"val\": was a boolean node with value that was <false>\n" + " }\n" + " \"bar\": was not a number node, but a string node\n" + " ...\n" + "}" )); }
static void fail(@Nullable Object actualValue, Matcher<?> matcher) { Description description = new StringDescription() .appendText("\nExpected: ") .appendDescriptionOf(matcher) .appendText("\n but: "); matcher.describeMismatch(actualValue, description); AssertionError assertionError = new AssertionError(description.toString()); assertionError.setStackTrace(ObjectChecker.trimStackTrace(assertionError.getStackTrace())); throw assertionError; }
@Step("Matching Actual - {1} and Expected {2}") public static <T> void assertThat(String reason, T actual, Matcher<? super T> matcher) { if (!matcher.matches(actual)) { Description description = new StringDescription(); description.appendText(reason) .appendText("\nExpected: ") .appendDescriptionOf(matcher) .appendText("\n but: "); matcher.describeMismatch(actual, description); ScreenShotUtil.takeScreenShot(); throw new AssertionError(description.toString()); } }
@Test public void description_adds_context() { Matcher<Exception> matcher = whereCauseMessage(equalTo("message")); StringDescription description = new StringDescription(); matcher.describeTo(description); assertThat(description.toString()).isEqualTo("Expecting exception cause to contain \"message\""); }
@Test public void description_adds_context() { Matcher<Exception> matcher = causeOf(RuntimeException.class); StringDescription description = new StringDescription(); matcher.describeTo(description); assertThat(description.toString()).isEqualTo("Expecting exception to be instance of class java.lang.RuntimeException"); }
@Test public void testInvokingDescribesToUpdatesDescription() { Builder<Map<String, Object>> builder = new Builder<>(); FormConditions formConditions = builder.whereBoolean( "boolean", isReturnedIn(map -> map.get("boolean")) ).whereString( "string", isReturnedIn(map -> map.get("string")) ).build(); Description description = new StringDescription(); formConditions.describeTo(description); StringBuilder stringBuilder = new StringBuilder(); String expected = stringBuilder.append( "a Form...\n\t...that should have a non empty title\n\t...that " ).append( "should have a non empty description\n\t...that should return " ).append( "something that is <true>\n\t...that should return something that " ).append( "is \"String\"\n" ).toString(); assertThat(description.toString(), is(expected)); }
@Test public void testInvokingMatchesUpdatedDescription() { Builder<Map<String, Object>> builder = new Builder<>(); FormConditions formConditions = builder.whereBoolean( "boolean", isReturnedIn(__ -> null) ).whereString( "string", isReturnedIn(__ -> null) ).build(); Description description = new StringDescription(); Form.Builder<Map<String, Object>> formBuilder = Form.Builder.empty(); Form<Map<String, Object>> form = formBuilder.title( __ -> "title" ).description( __ -> "description" ).constructor( HashMap::new ).build(); boolean matchesElement = formConditions.matches(form); formConditions.describeMismatch(form, description); String expected = "was a Form...\n\t...that should have returned something that is " + "<true> instead of null\n\t...that should have returned " + "something that is \"String\" instead of null\n"; assertThat(matchesElement, is(false)); assertThat(description.toString(), is(expected)); }
@Test public void testInvokingMatchesElementInStrictModeUpdatedDescription() { Conditions.Builder builder = new Conditions.Builder(); Conditions conditions = builder.where( "geek", is(aJsonBoolean(true)) ).where( "apio", is(aJsonString(equalTo("Live long and prosper"))) ).build(); Description description = new StringDescription(); JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("geek", true); jsonObject.addProperty("number", 42); jsonObject.addProperty("other", "apio"); jsonObject.addProperty("apio", "Live long and prosper"); boolean matchesElement = conditions.matches(jsonObject); conditions.describeMismatch(jsonObject, description); String expected = "was a JSON object with more fields than validated. Extra keys: " + "number, other"; assertThat(matchesElement, is(false)); assertThat(description.toString(), is(expected)); }