Question

I want to verify that a collection contains at least one non-null element. I have tried is(not(empty())), however this passes in the test below.

import org.junit.Test;

import java.util.ArrayList;
import java.util.Collection;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.not;

public class SandBoxTest {
    @Test
    public void shouldTestThis() {
        Collection<Integer> collection = new ArrayList<Integer>();
        collection.add(null);

        assertThat(collection, is(not(empty())));
    }
}

Is there an elegant/simple way to do this?

Things That Don't Work

@Test
public void should(){
    Collection<String> collection = new ArrayList();
    collection.add("gfas");
    collection.add("asda");
    assertThat(collection, contains(notNullValue()));
}

java.lang.AssertionError: 
Expected: iterable containing [not null]
     but: Not matched: "asda"
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
Was it helpful?

Solution

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

...

assertThat(collection, hasItem(notNullValue(Integer.class)));

Unfortunately, there is a bug in Java 1.6 that means you might have to split it onto 2 lines as described here if you are using 1.6:

Matcher<Iterable<? super String>> matcher = hasItem(notNullValue(Integer.class));
assertThat(collection, matcher);

EDIT Here is the FEST Assert example you asked for:

import static org.fest.assertions.api.Assertions.assertThat;
...
assertThat(collection).doesNotContainNull();

FEST requires only a single static import so you get full IDE auto completion.

OTHER TIPS

I just ran into the same problem and solved it as follows.

The basic idea is that if the collection has only null elements, converted to a set it will contain just one element and it will be null. If not so, then the collection contains at least one non-null element.

I wrote a matcher, and tried it with this test:

import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
import static personal.CollectionOfNullsMatcher.collectionOfNulls;


public class SimpleTest {

    @Test
    public void should_check_collection_for_non_null_values() {
        Collection<String> testedCollection = new ArrayList<String>();
        testedCollection.add(null);

        assertThat(testedCollection, is(collectionOfNulls()));

        testedCollection.add("any");

        assertThat(testedCollection, is(not(collectionOfNulls())));
    }
}

class CollectionOfNullsMatcher extends TypeSafeMatcher<Collection> {

    @Override
    protected boolean matchesSafely(final Collection collection) {
        Set<Object> set = new HashSet<Object>(collection);
        return (set.size() == 1) && (set.toArray()[0] == null);
    }

    @Override
    public void describeTo(final Description description) {
        description.appendText("collection of nulls");
    }

    @Factory
    public static <T> Matcher<Collection> collectionOfNulls() {
        return new CollectionOfNullsMatcher();
    }
}

Of course, in a real project, the matcher should be placed together with its brothers :)

Hope it helps.

You can try the following:

public void shouldTestThis() {
        Collection<Integer> collection = new ArrayList<Integer>();
        collection.add(null);
        collection.removeAll(Collections.singleton(null)); // remove all "null" elements from collection
        assertThat(collection, is(not(empty())));
    }

As ajb notices, if you want to left your array unmodified, you should use an iterator and check each element until the end of the collection or a non null one.

You're on the right track, chaining Matcher instances. You just need the hasItem matcher (like I've suggested here) instead of contains.

Creates a matcher for Iterables that only matches when a single pass over the examined Iterable yields at least one item that is matched by the specified itemMatcher. Whilst matching, the traversal of the examined Iterable will stop as soon as a matching item is found.

For example,

Collection<Integer> collection = new ArrayList<Integer>();
collection.add(null);

assertThat(collection, hasItem(is(not(nullValue()))));

will fail with

java.lang.AssertionError: 
Expected: a collection containing is not null
     but: was null
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:8)
    at com.example.ExampleTest.should(ExampleTest.java:21)
    at [...]

whereas

Collection<Integer> collection = new ArrayList<Integer>();
collection.add(null);
collection.add("hey");
collection.add(null);

assertThat(collection, hasItem(is(not(nullValue()))));
// or shortened
assertThat(collection, hasItem(notNullValue()));

will succeed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top