hamcrest - 比较集合中的项目
hamcrest - compare items in the collection
任何人都可以向我解释 hamcrest 如何比较集合以及库中的不同方法有什么用?
我想了解 IsIterableContainingInAnyOrder#containsInAnyOrder 方法是如何工作的。
IsIterableContainingInAnyOrderclass:
中有3个重载方法
containsInAnyOrder(T... items)
containsInAnyOrder(Matcher<? super T>... itemMatchers)
containsInAnyOrder(java.util.Collection<Matcher<? super T>> itemMatchers)
我的测试用例:
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)
,是真的吗?
但是如何使用 IsIterableContainingInAnyOrder
中剩余的方法呢?有什么方法可以比较集合而不将它们转换为数组吗?
您的代码在 JDK 1.8.0_12、Hamcrest 1.3 和 JUnit 4.12 的第一种形式中编译得很好,尽管由于 它没有产生预期的结果gotcha我会在下面解释
我只能猜测您可能有多种库版本,或 jdk,或类似的东西。但是,我认为这并不重要,因为我提到了 gotcha。
Can anyone explain to me how hamcrest compares collections and and what the different methods from the library are for?
简而言之,您可以提供自己的 array/collection 个匹配器,或者提供它将为其创建匹配器的项目数组。之后,根据生成的匹配器列表验证实际项目。
如果您检查 the sources,您会看到 IsIterableContainingInAnyOrder
构造函数接受一组匹配器:
public IsIterableContainingInAnyOrder(Collection<Matcher<? super T>> matchers) {
this.matchers = matchers;
}
...虽然您想知道的方法是 工厂方法 ,其中 return 一个 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);
}
如您所见,为每个项目创建了一个匹配器,有点像 gotcha:
- 如果您传递一个参数数组,您将获得每个项目的匹配器
assertThat(actual, containsInAnyOrder("one", "two", "four"));
产生:
java.lang.AssertionError:
Expected: iterable over ["one", "two", "four"] in any order
but: No item matches: "four" in ["two", "one"]
- 如果你传递一个列表,它会算作一个 1 个参数数组,并且只会为列表本身创建 1 个匹配器
assertThat(actual, containsInAnyOrder(Arrays.asList("one", "two", "four")))
产生:
java.lang.AssertionError:
Expected: iterable over [<[one, two, four]>] in any order
but: Not matched: "two"
注意到细微差别了吗?
I found that it must be converted to the array in order to work (the
second assertion in the example):
Matchers.containsInAnyOrder(expected.toArray()));
I suppose that in
this case this method from the library is used:containsInAnyOrder(T...
items)
, is that true ?
But how remaining methods from IsIterableContainingInAnyOrder
can be
used ? Is there any way to compare collections without converting them
to the array?
只需按原样使用 内嵌形式:assertThat(myList, containsInAnyOrder("one", "two", "four"))
。我想这提供了更好的可读性并避免了不必要的变量或多余的编码,例如 expected 集合。通常您需要检查几项,而不是数百项,对吗?
任何人都可以向我解释 hamcrest 如何比较集合以及库中的不同方法有什么用?
我想了解 IsIterableContainingInAnyOrder#containsInAnyOrder 方法是如何工作的。
IsIterableContainingInAnyOrderclass:
containsInAnyOrder(T... items)
containsInAnyOrder(Matcher<? super T>... itemMatchers)
containsInAnyOrder(java.util.Collection<Matcher<? super T>> itemMatchers)
我的测试用例:
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)
,是真的吗?
但是如何使用 IsIterableContainingInAnyOrder
中剩余的方法呢?有什么方法可以比较集合而不将它们转换为数组吗?
您的代码在 JDK 1.8.0_12、Hamcrest 1.3 和 JUnit 4.12 的第一种形式中编译得很好,尽管由于 它没有产生预期的结果gotcha我会在下面解释
我只能猜测您可能有多种库版本,或 jdk,或类似的东西。但是,我认为这并不重要,因为我提到了 gotcha。
Can anyone explain to me how hamcrest compares collections and and what the different methods from the library are for?
简而言之,您可以提供自己的 array/collection 个匹配器,或者提供它将为其创建匹配器的项目数组。之后,根据生成的匹配器列表验证实际项目。
如果您检查 the sources,您会看到 IsIterableContainingInAnyOrder
构造函数接受一组匹配器:
public IsIterableContainingInAnyOrder(Collection<Matcher<? super T>> matchers) {
this.matchers = matchers;
}
...虽然您想知道的方法是 工厂方法 ,其中 return 一个 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);
}
如您所见,为每个项目创建了一个匹配器,有点像 gotcha:
- 如果您传递一个参数数组,您将获得每个项目的匹配器
assertThat(actual, containsInAnyOrder("one", "two", "four"));
产生:
java.lang.AssertionError:
Expected: iterable over ["one", "two", "four"] in any order
but: No item matches: "four" in ["two", "one"]
- 如果你传递一个列表,它会算作一个 1 个参数数组,并且只会为列表本身创建 1 个匹配器
assertThat(actual, containsInAnyOrder(Arrays.asList("one", "two", "four")))
产生:
java.lang.AssertionError:
Expected: iterable over [<[one, two, four]>] in any order
but: Not matched: "two"
注意到细微差别了吗?
I found that it must be converted to the array in order to work (the second assertion in the example):
Matchers.containsInAnyOrder(expected.toArray()));
I suppose that in this case this method from the library is used:containsInAnyOrder(T... items)
, is that true ?But how remaining methods from
IsIterableContainingInAnyOrder
can be used ? Is there any way to compare collections without converting them to the array?
只需按原样使用 内嵌形式:assertThat(myList, containsInAnyOrder("one", "two", "four"))
。我想这提供了更好的可读性并避免了不必要的变量或多余的编码,例如 expected 集合。通常您需要检查几项,而不是数百项,对吗?