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.