Строгое соответствие в hamcrest?

Я пытаюсь использовать 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"

person pihentagy    schedule 13.10.2016    source источник


Ответы (2)


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

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

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

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

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

Expecting
 <["a", "b", "c"]>
not to contain
 <["c", "e", "a"]>
but found
 <["c", "a"]>
person Roland Weisleder    schedule 13.10.2016

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"

person Danio    schedule 13.10.2016
comment
Спасибо, я мог бы написать свое собственное утверждение, но смысл такой библиотеки IMHO состоит в том, чтобы по умолчанию предоставлять значимое сообщение об ошибке. - person pihentagy; 13.10.2016