Строгое совпадение в подголовнике?

Я пытаюсь использовать Hamcrest, но постоянно сталкиваюсь со следующим:

Устройства Hamcrest имеют короткое замыкание, например, если я напишу:

 Assert.assertThat(list, everyItem(not(isIn(shouldNotBeInList))));

Сообщается только о первом неисправном элементе shouldNotBeInList. Я ожидаю, что тесты скажут мне как можно больше.

Могу ли я написать утверждения в Hamcrest, чтобы они хорошо отчитывались, чтобы сообщалось обо всех несоответствиях, или я должен создать свои собственные сопоставители или использовать другую библиотеку?

Пример вывода для

List<String> list = Arrays.asList("a", "b", "c");
List<String> shouldNotBeInList = Arrays.asList("c", "e", "a");

Обратите внимание, нет сообщения об ошибке для c

Expected: every item is not one of {"c", "e", "a"}
     but: an item was "a"

2 ответа

Hamcrest немного сложнее, когда дело доходит до читаемых сообщений об ошибках. Некоторые сопоставители создают полезное сообщение со всеми ошибками, другие (чаще всего) сообщают только о первой ошибке.

Конечно, вы можете создать свой собственный механизм сопоставления с "лучшей" реализацией и хорошим сообщением об ошибке. Делать это на одном или двух матчах - это нормально, но это может закончиться повторной реализацией Hamcrest.

Если вам удобнее использовать другую библиотеку, взгляните на AssertJ. Утверждение

Assertions.assertThat(list).doesNotContainAnyElementsOf(shouldNotBeInList);

выдает это сообщение об ошибке:

Expecting
 <["a", "b", "c"]>
not to contain
 <["c", "e", "a"]>
but found
 <["c", "a"]>
public static void main(String[] args) {
        List<String> list = Arrays.asList("a", "b", "c");
        List<String> shouldNotBeInList = Arrays.asList("c", "e", "a");

        Assert.assertThat(list, everyFullCheck(not(isIn(shouldNotBeInList))));
    }

    public static class EveryFullCheck<T> extends TypeSafeDiagnosingMatcher<Iterable<T>> {
        private final Matcher<? super T> matcher;

        public EveryFullCheck(Matcher<? super T> matcher) {
            this.matcher= matcher;
        }

        @Override
        public boolean matchesSafely(Iterable<T> collection, Description mismatchDescription) {
            boolean matches = true;
            for (T t : collection) {
                if (!matcher.matches(t)) {
                    if (!matches) {
                        mismatchDescription.appendText(", ");
                    }
                    mismatchDescription.appendText("an item ");
                    matcher.describeMismatch(t, mismatchDescription);
                    matches = false;
                }
            }
            return matches;
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("every item is ").appendDescriptionOf(matcher);
        }
    }

    private static <U> EveryFullCheck<U> everyFullCheck(Matcher<? super U> matcher) {
        return new EveryFullCheck<>(matcher);
    }
        }

Ожидаемый: каждый элемент не является одним из {"c", "e", "a"}, но: элемент был "a", элемент был "c"

Другие вопросы по тегам