21

What is the opposite of contains?

    List<String> list = Arrays.asList("b", "a", "c");
    // should fail, because "d" is not in the list

    expectedInList = new String[]{"a","b", "c", "d"};
    Assert.assertThat(list, Matchers.contains(expectedInList));


    // should fail, because a IS in the list
    shouldNotBeInList = Arrays.asList("a","e", "f", "d");
    Assert.assertThat(list, _does_not_contains_any_of_(shouldNotBeInList)));

what should be _does_not_contains_any_of_?

pihentagy
  • 5,975
  • 9
  • 39
  • 58
  • Can you just negate the `contains` method? i.e. `!contains(shouldNotBeInList)` I haven't done much of this, so I'm not sure if it'll work, but its worth a try. – Hypnic Jerk Oct 12 '16 at 14:49
  • 2
    @Michael Pickett: not(contains all elements) = contains not all elements – pihentagy Oct 12 '16 at 14:55
  • Are you using Hamcrest? If so, the syntax should be more like !anyOf(...). I think, just looking at the API as I've never used Hamcrest. – Robert Benson Oct 12 '16 at 14:57

5 Answers5

27

You can combine three built-in matchers in the following way:

import static org.hamcrest.Matchers.everyItem;
import static org.hamcrest.Matchers.isIn;
import static org.hamcrest.Matchers.not;

@Test
public void hamcrestTest() throws Exception {
    List<String> list = Arrays.asList("b", "a", "c");
    List<String> shouldNotBeInList = Arrays.asList("a", "e", "f", "d");
    Assert.assertThat(list, everyItem(not(isIn(shouldNotBeInList))));
}

Executing this test will give you:

Expected: every item is not one of {"a", "e", "f", "d"}
but: an item was "a"

eee
  • 3,241
  • 1
  • 17
  • 34
  • Thanks for the answer. Now I have a related question about matcher strictness: http://stackoverflow.com/questions/40015862/strict-matching-in-hamcrest – pihentagy Oct 13 '16 at 08:26
  • 1
    hmmm, and how to solve it for strings to check if a substring is not contained – fabb Oct 11 '18 at 10:39
  • 2
    after `hasItems()` method this is very counterintuitive. I was trying to use `not(hasItems())` fro a while with no success. Thanks for your answer. – Oleg Kuts May 06 '19 at 11:37
4

Try this method :

public <T> Matcher<Iterable<? super T>> doesNotContainAnyOf(T... elements)
{
    Matcher<Iterable<? super T>> matcher = null;
    for(T e : elements)
    {
        matcher = matcher == null ?
            Matchers.not(Matchers.hasItem(e)) :
            Matchers.allOf(matcher, Matchers.not(Matchers.hasItem(e)));
    }
    return matcher;
}

With this test case :

List<String> list = Arrays.asList("a", "b", "c");
// True
MatcherAssert.assertThat(list, doesNotContainAnyOf("z","e", "f", "d"));
// False
MatcherAssert.assertThat(list, doesNotContainAnyOf("a","e", "f", "d"));
ToYonos
  • 16,469
  • 2
  • 54
  • 70
2

From the JavaDoc, I can see a clunky way to do it. There is probably a better way! This tests whether the list doesn't contain a, and doesn't contain b, and ...

List<Matcher> individual_matchers = new ArrayList<Matcher>();
for( String s : shouldNotBeInList ) {
    individual_matchers.add(Matchers.not(Matchers.contains(s)); // might need to use Matchers.contains({s}) - not sure
}
Matcher none_we_do_not_want = Matchers.allOf(individual_matchers);
Assert.assertThat(list, none_we_do_not_want);

(haven't tested, probably buggy :/ hope it helps)

cxw
  • 16,685
  • 2
  • 45
  • 81
1

I had a have the same issue. My solution was just inverted logic for this match.

Following you can see the snippet of code:

this.mockMvc.perform(get("/posts?page=0&size=1")
                .with(httpBasic(magelan.getUserName(), magelan.getPassword()))
                .accept(MediaType.parseMediaType("text/html;charset=UTF-8")))
                .andExpect(status().isOk())
                .andExpect(content().contentType("text/html;charset=UTF-8"))
                .andExpect(content().string(allOf(
                        containsString("First post")
                )))
                .andExpect(content().string(allOf(
                        not(containsString("Second post"))
                )));
catch23
  • 17,519
  • 42
  • 144
  • 217
0

As a workaround, one can use the following:

list - shouldNotBeInList should equal to the list itself (need to convert to set)

    Set<String> strings = new HashSet<>(list);
    strings.removeAll(shouldNotBeInList);

    Set<String> asSet = new HashSet<>(list);
    Assert.assertTrue(strings.equals(asSet));

But there should be a better way, I hope.

pihentagy
  • 5,975
  • 9
  • 39
  • 58