Hamcrest匹配器使用项目的自定义匹配器按项目比较两个不同类型的集合

时间:2014-12-04 11:07:03

标签: java matcher hamcrest

我有两个对象集合。这两个集合中的对象具有不同的类型,并且有一个自定义匹配器来检查它们是否引用相同的东西。此外,集合的顺序相同。比方说,我们可以按名称比较这些集合中的实体,它们按该名称排序,我们有一个自定义匹配器,如果名称相同则返回true。

我需要的是一个匹配器,它将逐项迭代这两个集合,并使用现有的自定义匹配器比较这些对(我也可以修改它)。

有谁知道怎么做?

这就是我的意思:

List lA =....;
List lB =....;

// what i have:

for (int i = 0; i < lA.size(); i++) { assertThat(lA.get(i), matchesUsingMyCustomMatcher(lB.get(i)); }

// what i would like to have assertThat(lA, someMagicMatcher(myModifiedCustomMatcher(lB)));

1 个答案:

答案 0 :(得分:0)

让我们考虑一下这个测试:

@Test
public void test() throws Exception {
    List<MyType1> expected = ...;
    List<MyType2> actual = ...;

    assertThat(actual, containsUsingCustomMatcher(expected));
}

您可以使用以下辅助函数(matchesUsingMyCustomMatcher与示例中的函数相同)。

private Matcher<Iterable<? extends MyType2>> containsUsingCustomMatcher(List<MyType1> items) {
    List<Matcher<? super MyType2>> matchers = new ArrayList<Matcher<? super MyType2>>();
    for (MyType1 item : items) {
        matchers.add(matchesUsingMyCustomMatcher(item));
    }
    return Matchers.contains(matchers);
}

通用方法

对于更可重用的方法,以下内容可能对您有所帮助。首先,我们需要一个通用的辅助函数。

public static <T, R> Matcher<Iterable<? extends R>> containsUsingCustomMatcher(List<T> items, MatcherFunction<T, R> matcherFunction) {
    return Matchers.contains(createMatchers(items, matcherFunction));
}

private static <R, T> List<Matcher<? super R>> createMatchers(List<T> items, MatcherFunction<T, R> matcherFunction) {
    List<Matcher<? super R>> matchers = new ArrayList<Matcher<? super R>>();
    for (T item : items) {
        matchers.add(matcherFunction.apply(item));
    }
    return matchers;
}

和界面MatcherFunction。此接口的实现必须创建适当的匹配器

public interface MatcherFunction<T, R> {
    Matcher<R> apply(T t);
}

实现与本答案第一部分相同的用法示例:

assertThat(actual, containsUsingCustomMatcher(expected, myCustomMatcherFunction()));

private MatcherFunction<MyType1, MyType2> myCustomMatcherFunction() {
    return new MatcherFunction<MyType1, MyType2>() {

        @Override
        public Matcher<MyType2> apply(MyType1 t) {
            return matchesUsingMyCustomMatcher(t);
        }
    };
}

Java 8注意:

这些匿名类看起来很丑陋。使用Java 8,您只需编写

即可
assertThat(actual, containsUsingCustomMatcher(expected, this::matchesUsingMyCustomMatcher));