Утверждение значений внутри различных пользовательских объектов с помощью hamcrest

Я новичок в использовании hamcrest для утверждений, и у меня уже есть довольно неприятный случай для тестирования.

У нас есть 2 массива различных пользовательских объектов: FilterItem и MyEnum. Оба содержат свойство, скажем, «значение», которое должно быть равным для прохождения модульных тестов. Поскольку объекты разные, я не могу просто assertThat (filterItems, hasItems(expectedEnums)), поэтому я хотел бы утвердить содержащиеся в них значения, что значительно усложняет задачу.

В каждом юнит-тесте, где я хотел бы подтвердить это, я извлекал логику утверждения в новый метод, как показано ниже:

private void assertIfFilterItemValuesAreEqualToExpectedEnumValues(ArrayList<FilterItem> filterItems, ArrayList<MyEnum> expectedEnums)
{
   ArrayList<String> filterItemValues = getFilterItemValues(filterItems);

   assertEquals(expectedEnums.size(), filterItemValues.size());
   // This assert prevents unittests to pass unfairly, in case the array is empty
   assertFalse("No expectedEnums to assert!", expectedEnums.isEmpty());

   for (MyEnum myEnum : expectedEnums)
   {
      String myEnumValue = myEnum.getValue();
      assertThat(filterItemValues, hasItem(myEnumValue));
   }
 }

private ArrayList<String> getFilterItemValues(ArrayList<FilterItem> filterItems)
{
   ArrayList<String> filterItemValues = new ArrayList<>();
   for (FilterWaardeItem filterItem : filterItems)
   {
      filterItemValues.add(filterItem.value);
   }
   return filterItemValues;
}

Сейчас все юнит-тесты проходят, поэтому я думаю, что реализация правильная, но мне кажется, что реализация могла бы быть проще. Я чувствую, что, по крайней мере, цикл for для перечисления можно было бы исключить. Кроме того, если бы решение могло сделать 2 утверждения перед циклом for ненужными, это было бы здорово! Вероятно, hasProperty() и contains() могут быть частью решения?

Любой совет?

пс. текущий тест не утверждает, является ли порядок списков одинаковым, но это следующий модульный тест, который я хотел бы создать. Если бы кто-нибудь мог дать хорошее решение и для этого (без использования всех циклов for), я был бы очень признателен!


person Patrick Kuijpers    schedule 19.04.2016    source источник


Ответы (2)


Вы можете заранее сопоставить фактический и ожидаемый список, а затем использовать contains:

private void assertIfFilterItemValuesAreEqualToExpectedEnumValues(ArrayList<FilterItem> filterItems, ArrayList<MyEnum> expectedEnums) {
    List<String> actual = filterItems.stream()
            .map(item -> item.value)
            .collect(toList());
    String[] expected = expectedEnums.stream()
            .map(myEnum -> myEnum.getValue())
            .toArray(String[]::new);

    assertThat(actual, contains(expected));
}

Это также утверждает, что порядок тот же. Я использовал новый java-8. поток API для сопоставления.

person eee    schedule 19.04.2016

Вы можете использовать метод hamcrest contains, который принимает список совпадений. Вы создаете список сопоставителей из expectedEnums, являющегося каждым элементом в списке, сопоставителем hasProperty с перечислением в списке.

    final List<Matcher<? super Object>> enumListMatcher = expectedEnums.stream()
            .map(myEnum -> hasProperty("value", is(myEnum.getValue()))).collect(Collectors.toList());
    assertThat(filterItems, contains(enumListMatcher));

ПРИМЕЧАНИЕ: это работает до тех пор, пока у вас есть геттер для value в FilterItem.

person Ruben    schedule 23.04.2016