使用hamcrest在不同的自定义对象中声明值

时间:2016-04-19 09:09:18

标签: java unit-testing hamcrest

我很高兴使用hamcrest作为断言,而且我已经有一个非常讨厌的案例需要测试。

我们有两个不同的自定义对象的arraylists: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循环。另外,如果解决方案可以使for循环之前的2个断言也不必要,那就太棒了! 可能hasProperty()contains()可能是解决方案的一部分吗?

有什么建议吗?

PS。当前的测试并没有断言列表的顺序是否相同,而是我想要创建的下一个单元测试。如果有人能为这一个提供一个很好的解决方案(不使用所有的for循环),我真的很感激它!

2 个答案:

答案 0 :(得分:0)

您可以预先映射实际和预期的列表,然后使用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));
}

这也断言订单是一样的。我使用新的流api进行映射。

答案 1 :(得分:0)

您可以使用接受匹配器列表的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的吸气剂,它就会有效。