有人能给我解释一下hamcrest是如何比较馆藏的,以及图书馆的不同方法是用来做什么的吗
我正在试图理解IsterableContainingAnyOrder#ContainingAnyOrder方法是如何工作的
ISiterableContainingAnyOrder类中有三个重载方法:
包含InAnyOrder(T...项)
包含InAnyOrder(匹配器
我的测试用例:
import org.hamcrest.Matchers;
import org.testng.annotations.Test;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertThat;
public class HamcrestCollections {
@Test
public void myTest(){
List<String> expected = Arrays.asList("one","two","four");
List<String> actual = Arrays.asList("two","one");
// This doesn't compile
assertThat(actual, Matchers.containsInAnyOrder(expected));
assertThat(actual, Matchers.containsInAnyOrder(expected.toArray()));
}
}
第一个断言没有编译,错误是:
Error:(19, 9) java: no suitable method found for assertThat(java.util.List<java.lang.String>,org.hamcrest.Matcher<java.lang.Iterable<? extends java.util.List<java.lang.String>>>)
method org.junit.Assert.<T>assertThat(java.lang.String,T,org.hamcrest.Matcher<? super T>) is not applicable
(cannot infer type-variable(s) T
(actual and formal argument lists differ in length))
method org.junit.Assert.<T>assertThat(T,org.hamcrest.Matcher<? super T>) is not applicable
(inferred type does not conform to upper bound(s)
inferred: java.util.List<java.lang.String>
upper bound(s): java.lang.Iterable<? extends java.util.List<java.lang.String>>,java.lang.Object)
我真的不明白这条信息中发生了什么。
我发现它必须转换为数组才能工作(示例中的第二个断言):
Matchers.containsInAnyOrder(expected.toArray()));
我假设在这种情况下,使用了库中的这个方法:
containsInAnyOrder(T…items)
,这是真的吗
但是如何使用中的剩余方法IsTerableContainingAnyOrder
?有没有办法在不将集合转换为数组的情况下比较集合?
您的代码在JDK1.8的第一种形式中编译得很好。0_12、Hamcrest 1.3和JUnit 4.12,尽管由于我将在下面解释的问题,它没有产生预期的结果。
我只能猜测,您可能有多种库版本,或jdk,或诸如此类的东西。然而,我相信这并不重要,因为我刚才提到的那个问题。
谁能给我解释一下hamcrest是如何比较收藏的,以及不同的方法是为了什么?
简而言之,您可以提供自己的匹配器数组/集合,也可以提供它将为其创建匹配器的项目数组。然后,根据生成的匹配器列表验证实际项目。
如果您检查源代码,您将看到ISiterableContainingAnyOrder
构造函数接受一组匹配器:
public IsIterableContainingInAnyOrder(Collection<Matcher<? super T>> matchers) {
this.matchers = matchers;
}
...而您想知道的方法是返回IsIterableContainingInAnyOrder
实例的工厂方法。一个是弃用的,我已经跳过了。然后我们有以下2,其中第一个委托给第二个,没有任何花哨的事情发生:
public static <T> Matcher<Iterable<? extends T>> containsInAnyOrder(Matcher<? super T>... itemMatchers) {
return containsInAnyOrder(Arrays.asList(itemMatchers));
}
public static <T> Matcher<Iterable<? extends T>> containsInAnyOrder(Collection<Matcher<? super T>> itemMatchers) {
return new IsIterableContainingInAnyOrder<T>(itemMatchers);
}
...最后我们有:
public static <T> Matcher<Iterable<? extends T>> containsInAnyOrder(T... items) {
List<Matcher<? super T>> matchers = new ArrayList<Matcher<? super T>>();
for (T item : items) {
matchers.add(equalTo(item));
}
return new IsIterableContainingInAnyOrder<T>(matchers);
}
如你所见,为每个项目创建了一个匹配器,这有点像一个陷阱:
断言(实际,包含InAnyOrder(一,二,四));
大喊:
java.lang.AssertionError:
Expected: iterable over ["one", "two", "four"] in any order
but: No item matches: "four" in ["two", "one"]
断言(实际,包含InAnyOrder(rrays.as列表(一,二,四)))
java.lang.AssertionError:
Expected: iterable over [<[one, two, four]>] in any order
but: Not matched: "two"
注意到细微的差别了吗?
我发现它必须转换为数组才能工作(示例中的第二个断言):
Matchers.containsInAnyOrder(expected.toArray()));
我想在这种情况下,使用了库中的此方法:包含InAnyOrder(T...项)
,这是真的吗?
但是如何使用IsIterableContainingInAnyOrder
中剩余的方法呢?有没有办法在不将集合转换为数组的情况下比较集合?
只需按原意使用内联表单:assertThat(myList,包含任意顺序(“一”、“二”、“四”))
。我认为这提供了更好的可读性,并避免了不必要的变量或多余的编码,例如预期的集合。通常你需要检查几个项目,而不是几百个,对吗?
但是想法 我该怎么写?
您能帮助我在使用方法时哪里出错了吗?
我有两个对象集合。这两个集合中的对象是不同类型的,并且有一个自定义匹配器来检查它们是否引用相同的东西。此外,集合的顺序相同。比方说,我们可以按名称比较这些集合中的实体,它们按该名称排序,我们有一个自定义匹配器,如果名称相同,则返回true。 我需要的是一个匹配器,它将逐项迭代这两个集合,并使用现有的自定义匹配器比较这些对(我也可以修改它)。 有人知道怎么做吗? 我的意思是:
我做错了什么,怎么修复?
我有一个集合,我想比较它是否包含所有的值。 这就是我想要的 我相信一定有其他方法来检查,而不是重复。