如何检查 hamcrest 集合中某些项目的大小和存在
How to check for size AND presence of some items in collections in hamcrest
我正在使用 Hamcrest 1.3 并尝试以更紧凑的方式实现以下目标。
考虑以下测试用例:
@Test
public void testCase() throws Exception {
Collection<String> strings = Arrays.asList(
"string one",
"string two",
"string three"
);
// variant 1:
assertThat(strings, hasSize(greaterThan(2)));
assertThat(strings, hasItem(is("string two")));
// variant 2:
assertThat(strings, allOf(
hasSize(greaterThan(2)),
hasItem(is("string two"))
));
}
这里的目标是检查集合的大小和要包含的一些特定项目。
在第一个变体可能并被接受的地方,做起来并不总是那么容易,因为集合本身可能是其他一些操作的结果,因此使用一个集合对其进行所有操作更有意义allOf
操作。这是在上面的第二个变体中完成的。
但是包含第二个变体的代码将导致以下编译时错误:
error: no suitable method found for allOf(Matcher<Collection<? extends Object>>,Matcher<Iterable<? extends String>>)
实际上是否有任何特定的方法可以使用单次操作(如 allOf
)来测试 Hamcrest 中集合的大小和项目?
猜测:你不会通过使用现有的匹配器到达那里。
但是编写自己的匹配器...只需要几分钟,一旦您理解了事情是如何组合在一起的。
也许你看看我的另一个 ;我在这里给出了一个完整的例子,说明如何编写自己的匹配器。那时候,我大概花了 15 分钟;尽管我以前从未编写过自定义匹配器。
我认为编译器无法理清泛型。以下对我有用 (JDK 8u102):
assertThat(strings, Matchers.<Collection<String>> allOf(
hasSize(greaterThan(2)),
hasItem(is("string two"))
));
我知道这个问题很老,但我仍然想回答它以防有人需要解释。
如果您想使用 allOf(...)
,只需确保嵌套匹配器 return 类型匹配。在您的测试用例中 hasSize
returns org.hamcrest.Matcher<java.util.Collection<? extends T>>
但 hasItem
产生 org.hamcrest.Matcher<java.lang.Iterable<? super T>>
。
在这种情况下,我建议使用 iterableWithSize(int size)
,其中 return 类型为 Matcher<java.lang.Iterable<T>>
,因此您可以:
assertThat(strings,
allOf(
iterableWithSize(greaterThan(2)),
hasItem("string two")
)
);
有一个简单但老实说有点隐藏的方法来测试列表大小和项目匹配:contains
contains
使用一个 Matcher,检查可迭代对象(例如列表)是否只有一个项目并且该项目与给定的 Matcher
匹配
contains(E... items)
(任意数量的匹配器)检查迭代器是否具有与给定匹配器数量一样多的项目,并且每个项目都与给定匹配器之一匹配。请注意 Matchers 不能匹配超过一项,否则结果可能与您预期的不同
所以总结 contains
隐式检查正确的大小(根据给定的 Matchers 的数量)
如果您对给定的尺寸匹配不感兴趣,请使用 hasItem/hasItems
我正在使用 Hamcrest 1.3 并尝试以更紧凑的方式实现以下目标。
考虑以下测试用例:
@Test
public void testCase() throws Exception {
Collection<String> strings = Arrays.asList(
"string one",
"string two",
"string three"
);
// variant 1:
assertThat(strings, hasSize(greaterThan(2)));
assertThat(strings, hasItem(is("string two")));
// variant 2:
assertThat(strings, allOf(
hasSize(greaterThan(2)),
hasItem(is("string two"))
));
}
这里的目标是检查集合的大小和要包含的一些特定项目。
在第一个变体可能并被接受的地方,做起来并不总是那么容易,因为集合本身可能是其他一些操作的结果,因此使用一个集合对其进行所有操作更有意义allOf
操作。这是在上面的第二个变体中完成的。
但是包含第二个变体的代码将导致以下编译时错误:
error: no suitable method found for allOf(Matcher<Collection<? extends Object>>,Matcher<Iterable<? extends String>>)
实际上是否有任何特定的方法可以使用单次操作(如 allOf
)来测试 Hamcrest 中集合的大小和项目?
猜测:你不会通过使用现有的匹配器到达那里。
但是编写自己的匹配器...只需要几分钟,一旦您理解了事情是如何组合在一起的。
也许你看看我的另一个
我认为编译器无法理清泛型。以下对我有用 (JDK 8u102):
assertThat(strings, Matchers.<Collection<String>> allOf(
hasSize(greaterThan(2)),
hasItem(is("string two"))
));
我知道这个问题很老,但我仍然想回答它以防有人需要解释。
如果您想使用 allOf(...)
,只需确保嵌套匹配器 return 类型匹配。在您的测试用例中 hasSize
returns org.hamcrest.Matcher<java.util.Collection<? extends T>>
但 hasItem
产生 org.hamcrest.Matcher<java.lang.Iterable<? super T>>
。
在这种情况下,我建议使用 iterableWithSize(int size)
,其中 return 类型为 Matcher<java.lang.Iterable<T>>
,因此您可以:
assertThat(strings,
allOf(
iterableWithSize(greaterThan(2)),
hasItem("string two")
)
);
有一个简单但老实说有点隐藏的方法来测试列表大小和项目匹配:contains
contains
使用一个 Matcher,检查可迭代对象(例如列表)是否只有一个项目并且该项目与给定的 Matcher
contains(E... items)
(任意数量的匹配器)检查迭代器是否具有与给定匹配器数量一样多的项目,并且每个项目都与给定匹配器之一匹配。请注意 Matchers 不能匹配超过一项,否则结果可能与您预期的不同
所以总结 contains
隐式检查正确的大小(根据给定的 Matchers 的数量)
如果您对给定的尺寸匹配不感兴趣,请使用 hasItem/hasItems