Reputation: 20119
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)
Upvotes: 7
Views: 13200
Reputation: 279890
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
Iterable
s that only matches when a single pass over the examinedIterable
yields at least one item that is matched by the specifieditemMatcher
. Whilst matching, the traversal of the examinedIterable
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.
Upvotes: 1
Reputation: 874
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.
Upvotes: 2
Reputation: 4048
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.
Upvotes: 7
Reputation: 2246
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.
Upvotes: 1