Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I assert an Iterable contains elements with a certain property?

People also ask

Is there an assert contains?

Assert. Contains is used to test whether an object is contained in a collection.

What is assert assertSame?

assertEquals: Asserts that two objects are equal. assertSame: Asserts that two objects refer to the same object. In other words. assertEquals: uses the equals() method, or if no equals() method was overridden, compares the reference between the 2 objects.

How do you assert a list in Java?

List first = Arrays. asList(1, 3, 4, 6, 8); List second = Arrays. asList(8, 1, 6, 3, 4); List third = Arrays. asList(1, 3, 3, 6, 6);


Thank you @Razvan who pointed me in the right direction. I was able to get it in one line and I successfully hunted down the imports for Hamcrest 1.3.

the imports:

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;

the code:

assertThat( myClass.getMyItems(), contains(
    hasProperty("name", is("foo")), 
    hasProperty("name", is("bar"))
));

Try:

assertThat(myClass.getMyItems(),
                          hasItem(hasProperty("YourProperty", is("YourValue"))));

Its not especially Hamcrest, but I think it worth to mention here. What I use quite often in Java8 is something like:

assertTrue(myClass.getMyItems().stream().anyMatch(item -> "foo".equals(item.getName())));

(Edited to Rodrigo Manyari's slight improvement. It's a little less verbose. See comments.)

It may be a little bit harder to read, but I like the type and refactoring safety. Its also cool for testing multiple bean properties in combination. e.g. with a java-like && expression in the filter lambda.


AssertJ provides an excellent feature in extracting() : you can pass Functions to extract fields. It provides a check at compile time.
You could also assert the size first easily.

It would give :

import static org.assertj.core.api.Assertions;

Assertions.assertThat(myClass.getMyItems())
          .hasSize(2)
          .extracting(MyItem::getName)
          .containsExactlyInAnyOrder("foo", "bar"); 

containsExactlyInAnyOrder() asserts that the list contains only these values whatever the order.

To assert that the list contains these values whatever the order but may also contain other values use contains() :

.contains("foo", "bar"); 

As a side note : to assert multiple fields from elements of a List , with AssertJ we do that by wrapping expected values for each element into a tuple() function :

import static org.assertj.core.api.Assertions;
import static org.assertj.core.groups.Tuple;

Assertions.assertThat(myClass.getMyItems())
          .hasSize(2)
          .extracting(MyItem::getName, MyItem::getOtherValue)
          .containsExactlyInAnyOrder(
               tuple("foo", "OtherValueFoo"),
               tuple("bar", "OtherValueBar")
           ); 

Assertj is good at this.

import static org.assertj.core.api.Assertions.assertThat;

    assertThat(myClass.getMyItems()).extracting("name").contains("foo", "bar");

Big plus for assertj compared to hamcrest is easy use of code completion.


As long as your List is a concrete class, you can simply call the contains() method as long as you have implemented your equals() method on MyItem.

// given 
// some input ... you to complete

// when
List<MyItems> results = service.getMyItems();

// then
assertTrue(results.contains(new MyItem("foo")));
assertTrue(results.contains(new MyItem("bar")));

Assumes you have implemented a constructor that accepts the values you want to assert on. I realise this isn't on a single line, but it's useful to know which value is missing rather than checking both at once.


AssertJ 3.9.1 supports direct predicate usage in anyMatch method.

assertThat(collection).anyMatch(element -> element.someProperty.satisfiesSomeCondition())

This is generally suitable use case for arbitrarily complex condition.

For simple conditions I prefer using extracting method (see above) because resulting iterable-under-test might support value verification with better readability. Example: it can provide specialized API such as contains method in Frank Neblung's answer. Or you can call anyMatch on it later anyway and use method reference such as "searchedvalue"::equals. Also multiple extractors can be put into extracting method, result subsequently verified using tuple().