JUnit и hamcrest: может containsInAnyOrder() рассказать больше о несоответствии?

При тестировании Set с помощью JUnit и сопоставителей Hamcrest я заметил этот метод Matchers.contains() дает довольно хорошее представление о том, что не так с тестом. С другой стороны, отчет о различиях Matchers.containsInAnyOrder() практически бесполезен. Вот тестовый код:

Простой компонент:

public class MyBean {
    private Integer id;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }       
}

Тест JUnit:

import java.util.HashSet;
import java.util.Set;

import org.junit.Test;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

public class MyTest {

    @Test
    public void hamcrestTest() {
        Set<MyBean> beanSet = new HashSet<MyBean>();

        MyBean bean = new MyBean();
        bean.setId(1);
        beanSet.add(bean);

        bean = new MyBean();
        bean.setId(2);
        beanSet.add(bean);

        assertThat(beanSet, contains(
                hasProperty("id", is(1)),
                hasProperty("id", is(3))
                ));
    }
}

Как вы можете видеть, фактические идентификаторы компонентов — 1 и 2, а ожидаемые — 1 и 3, поэтому тест не пройден.

Результат проверки:

java.lang.AssertionError: 
Expected: iterable over [hasProperty("id", is <1>), hasProperty("id", is <3>)] in any order
     but: Not matched: <MyBean@4888884e

Если я переключусь на метод Matchers.contains(), результат будет намного информативнее:

java.lang.AssertionError: 
Expected: iterable containing [hasProperty("id", is <1>), hasProperty("id", is <3>)]
     but: item 0: property 'id' was <2>

К сожалению, поскольку набор не заказан, contains() в данном случае не подходит.


Наконец, вопрос:
Можно ли каким-то образом получить лучший отчет об ошибке при утверждении Set с подколенным сухожилием?


person Sergey Pauk    schedule 15.04.2015    source источник
comment
Если вы добавите метод toString в свой MyBean, вы должны получить лучший результат...   -  person assylias    schedule 15.04.2015


Ответы (1)


У Hamcrest, похоже, есть разные реализации того, как сообщается о несоответствиях для сопоставителей contains и containsInAnyOrder.

containsInAnyOrder просто дает вам значение toString() элемента, делая это:

mismatchDescription.appendText("Not matched: ").appendValue(item);

В то время как сопоставитель contains работает лучше, делегируя функции describeMismatch() фактического сопоставителя:

matcher.describeMismatch(item, mismatchDescription);

Следовательно, в этом случае вы видите дополнительную информацию сопоставителя hasProperty, но не при использовании containsInAnyOrder.

Я думаю, что лучшее, что вы можете сделать в этом случае, это реализовать toString() для вашего класса MyBean.

Об этом уже сообщалось: https://github.com/hamcrest/JavaHamcrest/issues/ 47

person K Erlandsson    schedule 15.04.2015