private Matcher<String> matchesPattern(final String pattern) { return new DiagnosingMatcher<String>() { @Override protected boolean matches(Object item, Description mismatchDescription) { if (!((String) item).matches(pattern)) { mismatchDescription.appendValue(item).appendText(" did not match regex ").appendValue(pattern); } return ((String) item).matches(pattern); } @Override public void describeTo(Description description) { description.appendText("a string matching regex ").appendValue(pattern); } }; }
@Factory private static DiagnosingMatcher<Object> translateTo(HttpStatus status) { return new DiagnosingMatcher<Object>() { private static final String EXCEPTION = "EXCEPTION"; @Override public void describeTo(final Description description) { description.appendText("does not translate to ").appendText(status.toString()); } @SuppressWarnings("unchecked") protected boolean matches(final Object item, final Description mismatch) { if (item instanceof Class) { if (((Class) item).getClass().isInstance(Throwable.class)) { Class<? extends Throwable> type = (Class<? extends Throwable>) item; try { Throwable exception = type.getConstructor(String.class).newInstance(EXCEPTION); Mono.just(exception).transform(ThrowableTranslator::translate).subscribe(translator -> { assertThat(translator.getMessage(), is(EXCEPTION)); assertThat(translator.getHttpStatus(), is(status)); }); } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException cause) { throw new AssertionError("This exception class has not constructor with a String", cause); } return true; } } mismatch.appendText(item.toString()); return false; } }; }
public static DiagnosingMatcher<Table> hasRowThat(Matcher<?>... cells) { return new DiagnosingMatcher<Table>() { @Override protected boolean matches(Object item, Description mismatchDescription) { TableModel model = ((Table) item).getModel(); outer: for (int row = 0; row < model.getRowCount(); row++) { mismatchDescription.appendText("\nRow " + row + ": "); for (int col = 0; col < cells.length; col++) { mismatchDescription.appendText("\n Column " + col + ": "); cells[col].describeMismatch(model.getValue(row, col), mismatchDescription); if (!cells[col].matches(model.getValue(row, col))) { continue outer; } } return true; } return false; } @Override public void describeTo(Description description) { description.appendText("a table having at least one row that\n"); for (int col = 0; col < cells.length; col++) { description.appendText("column " + col + ": "); cells[col].describeTo(description); description.appendText("\n"); } } }; }
public static <T> Function1<T, String> diagnoseMismatch(final DiagnosingMatcher matcher) { return t -> { StringDescription mismatchDescription = new StringDescription(); matcher.describeMismatch(t, mismatchDescription); return mismatchDescription.toString(); }; }
/** * A bit better version of CoreMatchers.allOf. * For example: * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre> */ @SafeVarargs public static <T> Matcher<T> allOf(Matcher<? super T>... matchers) { return new DiagnosingMatcher<T>() { @Override protected boolean matches(Object o, Description mismatch) { boolean ret = true; for (Matcher<? super T> matcher : matchers) { if (!matcher.matches(o)) { if (ret) mismatch.appendText("("); mismatch.appendText("\n "); mismatch.appendDescriptionOf(matcher).appendText(" "); matcher.describeMismatch(o, mismatch); ret = false; } } if (!ret) mismatch.appendText("\n)"); return ret; } @Override public void describeTo(Description description) { description.appendList("(\n ", " " + "and" + "\n ", "\n)", Arrays.stream(matchers).collect(toList())); } }; }
public static <T> Function1<T, String> describeMismatch(final Matcher<? super T> matcher) { if (matcher instanceof DiagnosingMatcher) return diagnoseMismatch((DiagnosingMatcher) matcher); return returns1(StringDescription.asString(matcher)); }
public static <T> Function1<T, String> diagnoseMismatch(Class<T> type, final DiagnosingMatcher matcher) { return diagnoseMismatch(matcher); }