匹配器IsIterableContainingInAnyOrder
对静态工厂方法containsInAnyOrder
有两个重载(两者都有返回类型Matcher<java.lang.Iterable<? extends T>>
):
containsInAnyOrder(java.util.Collection<Matcher<? super T>> itemMatchers)
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
的第二个重载。
现在,当我将断言更改为此(与documentation of the first overload中给出的示例完全匹配时):
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。
答案 0 :(得分: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"))));
答案 1 :(得分:2)
当你匹配你自己的对象而不是简单的字符串时,这甚至会更难以使泛型工作得以解决。如果您正在使用问题的第一个示例中的varargs containsInAnyOrder(Matcher<? super T>... itemMatchers)
,那么您将获得针对varargs参数的未经检查的泛型数组警告。例如:
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);
答案 2 :(得分: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"));
}
}
请注意,如果您希望Type
调用containsInAnyOrder,则无法使用静态导入,这样就无需添加@SuppressWarnings("unchecked")