7

匹配器IsIterableContainingInAnyOrder对静态工厂方法有两个重载containsInAnyOrder(都有返回类型Matcher<java.lang.Iterable<? extends T>>):

  1. containsInAnyOrder(java.util.Collection<Matcher<? super T>> itemMatchers)
  2. containsInAnyOrder(Matcher<? super T>... itemMatchers)

现在考虑以下程序:

import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;

import java.util.Arrays;

import org.junit.Test;

public class SomeTest {

    @SuppressWarnings("unchecked")
    @Test
    public void foo() {
        assertThat(Arrays.asList("foo","bar"), 
                       containsInAnyOrder(equalTo("foo"), equalTo("bar")));
    }

}

将其作为 JUnit 测试执行时,它按预期通过。它使用containsInAnyOrder上面显示的第二个重载。

现在,当我将断言更改为此(与第一个重载文档中给出的示例完全匹配)时:

assertThat(Arrays.asList("foo","bar"), 
           containsInAnyOrder(Arrays.asList(equalTo("foo"), equalTo("bar"))));
                              ^^^^^^^^^^^^^^

它不再编译,因为现在编译器推断返回类型containsInAnyOrder

Matcher<Iterable<? extends List<Matcher<String>>>>

似乎编译器仍然选择第二个重载。如果它使用第一个,该示例应该可以工作。为什么它会这样?我怎样才能使这项工作?

我正在使用 Hamcrest 1.3 和 Oracle Java 1.7。

4

3 回答 3

4

它实际上匹配两个重载方法。我不确定为什么选择第一个,但您可以提供提示以使其选择正确的方法。

通过将参数转换为Collection

assertThat(Arrays.asList("foo","bar"),
        containsInAnyOrder((Collection)Arrays.asList(equalTo("foo"), equalTo("bar"))));

或通过将泛型类型 T 指定为<String>(但不适用于静态导入):

assertThat(Arrays.asList("foo","bar"),
        IsIterableContainingInAnyOrder.<String>containsInAnyOrder(Arrays.asList(equalTo("foo"), equalTo("bar"))));
于 2013-09-04T16:17:58.857 回答
3

当您匹配自己的对象而不是简单的字符串时,这甚至更难使泛型发挥作用。如果您containsInAnyOrder(Matcher<? super T>... itemMatchers)在问题的第一个示例中使用 varargs,您将收到Unchecked generics array creation for varargs parameter警告。例如:

assertThat(myDTOList, 
    containsInAnyOrder(sameStateAs(expectedMyDTO1), sameStateAs(expectedMyDTO2));

然后解决问题中所述OP的一种方法是定义匹配器集合,如下所示:

Collection<Matcher<? super MyDTO>> expectedMyDTOs = 
    Arrays.<Matcher<? super MyDTO>>asList(sameStateAs(expectedMyDTO1), sameStateAs(expectedMyDTO2));

// Use like this:
assertThat(myDTOList, 
    containsInAnyOrder(expectedMyDTOs);
于 2014-10-16T06:41:25.727 回答
2

使用 hamcrest 1.3,您可以使用Matchers该类而不是IsIterableContainingInAnyOrder直接使用 @eee 提到的。Matchers 实际上只是为您调用 IsIterableContainingInAnyOrder。

import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;

import org.hamcrest.Matchers;
import java.util.Arrays;
import org.junit.Test;

public class SomeTest
{
    @Test
    public void foo() {
        assertThat(Arrays.asList("foo","bar"), 
            Matchers.<OrderValidationStep>containsInAnyOrder("foo", "bar"));
    }
}

请注意,如果您想调用 containsInAnyOrder,则不能使用静态导入Type,这样就无需添加@SuppressWarnings("unchecked")

于 2015-07-02T11:01:57.803 回答