简体   繁体   中英

Test if list of lists contains specific element using assertThat

I tried to check if each list in a list of lists contains a specific value using Assert#assertThat .

I've written this code but it doesn't work. The test isn't compiled, code is underlined with a red line and an error message is shown (look at the comment):

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

And even with explicit types:

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

If it's just list of strings I could check if each string contains specific letter like that:

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

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

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

So what's wrong with my code? How could I fix it?

Imports:

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

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

Gradle dependencies:

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

I think everyItem matcher is not designed to work with hasItem and you fall into generics hell as you've found out.

I don't see a simple solution, other than defining a matcher that will "encapsulate" generics restrictions and will delegate to the hasItem matcher. Fortunately Defining a new matcher is really an easy task. Have a look:

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

This code snippet is self-explanatory. It delegates all the work to the existing matcher.

With this in mind you can rewrite your test as:

    @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")));
    }

I hope this helps, I tried a different way to search for the element. I used nested foreach loops to see if the list of lists contained that specific element.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM