断言数组中的一个字符串包含子串

7
List<String> expectedStrings = Arrays.asList("link1", "link2");
List<String> strings = Arrays.asList("lalala link1 lalalla", "lalalal link2 lalalla");

对于每个期望的字符串,我需要断言“strings”中的任何一个字符串都包含期望的字符串。我该如何使用Hamcrest进行断言?感谢您的关注。

你需要告诉我们你尝试过什么。 - Steve Smith
3个回答

7

更新

在查看这个旧答案后,我发现您可以使用更好的内置匹配器组合,从而使断言和错误消息更易读:

expectedStrings.forEach(expectedString -> 
    assertThat(strings, hasItem(containsString(expectedString))));

参考答案

您可以使用流轻松完成它:

assertThat(expectedStrings.stream().allMatch(
    expectedString -> strings.stream()
                             .anyMatch(string -> string.contains(expectedString))),
    is(true));
< p > allMatch 会确保检查所有的 expectedStrings,而使用 strings 上的 anyMatch,您可以有效地检查任何字符串是否包含期望的字符串。


这很好。我现在意识到我做了错误的推断,我的答案是错误的。干得好。 - David Conrad

1

目前,尽管您可以组合多个匹配器,但 Hamcrest 中还没有满足此要求的匹配器。

因此,在像您这样的情况下,我认为最好的解决方案是创建自己的匹配器。为什么?

  • 它可以被重复使用
  • 易于维护
  • 更易读

所以在您的情况下,您需要匹配第一个列表中包含第二个列表中任何字符串,您可以创建一个类似下面的 Matcher:

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));

0

我喜欢自定义匹配器的想法。你可以将流机制用作其核心。这里是一个简单(低效)的例子:

 assertThat( infoLogs.stream().filter(logItem -> logItem.contains("writing out group")).collect(Collectors.toList()).size()).isNotZero();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接