断言数组中的字符串之一包含子字符串
Assert that one of string in array contains substring
List<String> expectedStrings = Arrays.asList("link1", "link2");
List<String> strings = Arrays.asList("lalala link1 lalalla", "lalalal link2 lalalla");
对于每个 expectedString,我需要断言 'strings' 中的任何字符串都包含 expectedString。
我如何用 Hamcrest 断言这一点?
感谢您的关注。
更新
检查这个旧答案后,我发现您可以使用更好的 built-in 匹配器组合,使断言和错误消息更具可读性:
expectedStrings.forEach(expectedString ->
assertThat(strings, hasItem(containsString(expectedString))));
原答案供参考
您可以使用流很容易地做到这一点:
assertThat(expectedStrings.stream().allMatch(
expectedString -> strings.stream()
.anyMatch(string -> string.contains(expectedString))),
is(true));
allMatch
将确保检查所有 expectedStrings
,并且在 strings
上使用 anyMatch
可以有效地检查是否有任何字符串包含预期的字符串。
目前在 hamcrest 中没有任何符合此要求的匹配器,尽管您可以组合多个,但这是不可能的。
因此,在我看来,在像您这样的情况下,最好的解决方案是 创建您自己的匹配器 为什么?
- 可以重复使用
- 可维护
- 更具可读性
所以在你的情况下,你需要匹配第一个列表包含第二个列表的任何字符串,你可以创建一个匹配器,如下所示:
public class ContainsStringsOf extends BaseMatcher<List<String>> {
private final List<String> valuesToCompare;
public ContainsStringsOf(List<String> valuesToCompare) {
this.valuesToCompare = valuesToCompare;
}
@Override
public void describeTo(Description description) {
description.appendText("doesn't contains all of " + valuesToCompare.toString() + " text");
}
@Override
public boolean matches(Object o) {
List<String> values = (List<String>) o;
for (String valueToCompare : valuesToCompare) {
boolean containsText = false;
for (String value : values) {
if (value.contains(valueToCompare)) {
containsText = true;
}
}
if (!containsText) {
return false;
}
}
return true;
//note: you can replace this impl with java-8 @florian answer comparison
//return valuesToCompare.stream().allMatch(exp -> strings.stream().anyMatch(st-> st.contains(exp)))
}
@Factory
public static Matcher<List<String>> containsStringsOf(List<String> collection) {
return new ContainsStringsOf(collection);
}
}
然后就可以像使用hamcrest matcher一样使用了:
List<String> expectedStrings = Arrays.asList("link1", "link2");
List<String> strings = Arrays.asList("lalala link1 lalalla", "lalalal link2 lalalla");
Assert.assertThat(strings , containsStringsOf(expectedStrings));
List<String> expectedStrings = Arrays.asList("link1", "link2");
List<String> strings = Arrays.asList("lalala link1 lalalla", "lalalal link2 lalalla");
对于每个 expectedString,我需要断言 'strings' 中的任何字符串都包含 expectedString。 我如何用 Hamcrest 断言这一点? 感谢您的关注。
更新
检查这个旧答案后,我发现您可以使用更好的 built-in 匹配器组合,使断言和错误消息更具可读性:
expectedStrings.forEach(expectedString ->
assertThat(strings, hasItem(containsString(expectedString))));
原答案供参考
您可以使用流很容易地做到这一点:
assertThat(expectedStrings.stream().allMatch(
expectedString -> strings.stream()
.anyMatch(string -> string.contains(expectedString))),
is(true));
allMatch
将确保检查所有 expectedStrings
,并且在 strings
上使用 anyMatch
可以有效地检查是否有任何字符串包含预期的字符串。
目前在 hamcrest 中没有任何符合此要求的匹配器,尽管您可以组合多个,但这是不可能的。
因此,在我看来,在像您这样的情况下,最好的解决方案是 创建您自己的匹配器 为什么?
- 可以重复使用
- 可维护
- 更具可读性
所以在你的情况下,你需要匹配第一个列表包含第二个列表的任何字符串,你可以创建一个匹配器,如下所示:
public class ContainsStringsOf extends BaseMatcher<List<String>> {
private final List<String> valuesToCompare;
public ContainsStringsOf(List<String> valuesToCompare) {
this.valuesToCompare = valuesToCompare;
}
@Override
public void describeTo(Description description) {
description.appendText("doesn't contains all of " + valuesToCompare.toString() + " text");
}
@Override
public boolean matches(Object o) {
List<String> values = (List<String>) o;
for (String valueToCompare : valuesToCompare) {
boolean containsText = false;
for (String value : values) {
if (value.contains(valueToCompare)) {
containsText = true;
}
}
if (!containsText) {
return false;
}
}
return true;
//note: you can replace this impl with java-8 @florian answer comparison
//return valuesToCompare.stream().allMatch(exp -> strings.stream().anyMatch(st-> st.contains(exp)))
}
@Factory
public static Matcher<List<String>> containsStringsOf(List<String> collection) {
return new ContainsStringsOf(collection);
}
}
然后就可以像使用hamcrest matcher一样使用了:
List<String> expectedStrings = Arrays.asList("link1", "link2");
List<String> strings = Arrays.asList("lalala link1 lalalla", "lalalal link2 lalalla");
Assert.assertThat(strings , containsStringsOf(expectedStrings));