【问题标题】:Test if list of lists contains specific element using assertThat使用 assertThat 测试列表列表是否包含特定元素
【发布时间】:2021-04-03 18:30:45
【问题描述】:

我尝试使用Assert#assertThat 检查列表列表中的每个列表是否包含特定值。

我已经编写了这段代码,但它不起作用。 测试未编译,代码带有红线下划线并显示错误消息(查看注释):

    List<List<String>> testedList = new ArrayList<>();

    List<String> firstList = new ArrayList<>();
    firstList.add("1");
    firstList.add("2");

    List<String> secondList = new ArrayList<>();
    secondList.add("2");
    secondList.add("3");

    testedList.add(firstList);
    testedList.add(secondList);

    Assert.assertThat(testedList, CoreMatchers.everyItem(CoreMatchers.hasItem("2")));
    //          Required type       Provided
    // actual:  T                   List<java.util.List<java.lang.String>>
    // matcher: Matcher<? super T>  Matcher<Iterable<Iterable<? super String>>>

即使是显式类型:

    Assert.assertThat(testedList, CoreMatchers.<List<String>>everyItem(CoreMatchers.<String>hasItem("2")));
    // Required type: Matcher<List<String>> 
    // Provided:      Matcher<Iterable<? super String>>

如果它只是字符串列表,我可以检查每个字符串是否包含这样的特定字母:

    List<String> testedList = new ArrayList<>();

    testedList.add("1a");
    testedList.add("2a");

    Assert.assertThat(testedList, CoreMatchers.everyItem(CoreMatchers.containsString("a")));

那么我的代码有什么问题? 我该如何解决?

进口:

import org.hamcrest.CoreMatchers;
import org.junit.Assert;
import org.junit.Test;

import java.util.List;
import java.util.ArrayList;

Gradle 依赖项:

testCompile group: 'junit', name: 'junit', version: '4.12'

【问题讨论】:

  • 它不起作用是什么意思?第一个断言对我来说运行正常
  • 对我来说,它显示了我在评论中描述的错误消息
  • 错误是否发生在方法“everyItem”上?
  • @PabloB 它没有被编译。所有 Assert#assertThat 内容都会显示错误消息。

标签: java junit4 assert matcher hamcrest


【解决方案1】:

我认为 everyItem 匹配器不是为与 hasItem 一起工作而设计的,而且你已经发现你会陷入泛型地狱。

除了定义一个将“封装”泛型限制并将委托给hasItem 匹配器的匹配器之外,我没有看到一个简单的解决方案。幸运的是,定义一个新的匹配器确实是一件容易的事。看看:

private class HasItemMatcher<T> extends BaseMatcher<List<T>> {

        private final Matcher<Iterable<? super T>> iterableMatcher;
        public HasItemMatcher(T value) {
            this.iterableMatcher = CoreMatchers.hasItem(value);
        }

        @Override
        public boolean matches(Object item) {
            return iterableMatcher.matches(item);
        }

        @Override
        public void describeTo(Description description) {
            iterableMatcher.describeTo(description);
        }
    }

这个代码 sn-p 是不言自明的。它将所有工作委托给现有的匹配器。

考虑到这一点,您可以将测试重写为:

    @Test
    public void sampleTest() {
        List<List<String>> testedList = new ArrayList<>();

        List<String> firstList = new ArrayList<>();
        firstList.add("1");
        firstList.add("2");

        List<String> secondList = new ArrayList<>();
        secondList.add("2");
        secondList.add("3");

        testedList.add(firstList);
        testedList.add(secondList);

        Assert.assertThat(testedList, CoreMatchers.everyItem(new HasItemMatcher<>("2")));
    }

【讨论】:

    【解决方案2】:

    我希望这会有所帮助,我尝试了一种不同的方式来搜索元素。我使用嵌套的 foreach 循环来查看列表列表是否包含该特定元素。

        List<List<String>> testedList = new ArrayList<>();
        boolean exist = false;
    
        List<String> firstList = new ArrayList<>();
        firstList.add("1");
        firstList.add("2");
    
        List<String> secondList = new ArrayList<>();
        secondList.add("2");
        secondList.add("3");
    
        testedList.add(firstList);
        testedList.add(secondList);
    
        for(List <String> e : testedList){
            for(String i : e){
            if(i.equalsIgnoreCase("2"))
                exist = true;
            }
        }System.out.println(exist);`
    

    【讨论】:

    • 我不想在测试中使用 for 循环。
    猜你喜欢
    • 2011-12-28
    • 2011-03-16
    • 2020-01-10
    • 2022-09-23
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多