Is there any Hamcrest Matcher for java.util.Optional?
Asked Answered
D

5

23

I am looking for a Hamcrest Matcher to unit test methods that return a java.util.Optional type. Something like:

    @Test
    public void get__Null(){

        Optional<Element> element = Element.get(null);      
        assertThat( sasi , isEmptyOptional());
    }

    @Test
    public void get__GetCode(){

        Optional<Element> element = Element.get(MI_CODE);       
        assertThat( sasi , isOptionalThatMatches(allOf(hasproperty("code", MI_CODE),
                                                       hasProperty("id",   notNullValue())));
    }

Is there any implementation available throw the Maven Repository?

Devotional answered 8/6, 2016 at 13:25 Comment(3)
Why don't you just use equalTo(...)?Sherris
There are other ways to test the object. But on some cases the matcher will make our life easier. For example, to assert that one object has a bean with an Optional property with a value when you only want to check some fields. Or if the equals have some special implementation.Devotional
I am don't know your case well enough, but maybe this library could help you: github.com/shazam/shazamcrestSherris
T
20

Presently Java Hamcrest is using 1.6 version and is integrated with many projects that use older version of Java.

So the features related to Java 8 will be added in future versions that are Java 8 compatible. The solution proposed was to have an extension library that supports it, so that anyone who needs can use extension library.

I am the author of Hamcrest Optional and it is now available on Maven central.

Example: Checking if the Optional contains a string starting with some value

import static com.github.npathai.hamcrestopt.OptionalMatchers.hasValue;
import static org.hamcrest.Matchers.startsWith;

Optional<String> optional = Optional.of("dummy value");
assertThat(optional, hasValue(startsWith("dummy")));
Taffeta answered 15/8, 2016 at 19:8 Comment(0)
P
3

The Hamcrest Optional from Narendra Pathai does great job indeed.

import static com.github.npathai.hamcrestopt.OptionalMatchers.isEmpty;
import static com.github.npathai.hamcrestopt.OptionalMatchers.isPresent;
import static com.github.npathai.hamcrestopt.OptionalMatchers.isPresentAnd;
import static com.github.npathai.hamcrestopt.OptionalMatchers.isPresentAndIs;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
  @Test
  public void testOptionalValue() {
    Optional<String> option = Optional.of("value");
    assertTrue(option.isPresent()); // the old-fashioned, non-diagnosable assertion
    assertThat(option, isPresent());
    assertThat(option, isPresentAndIs("value"));
    assertThat(option, isPresentAnd(startsWith("v")));
    assertThat(option, isEmpty()); // fails
  }

The last assertion above fails and produces nice diagnosable message:

java.lang.AssertionError: 
Expected: is <Empty>
     but: had value "value"

Available on Maven :

<dependency>
  <groupId>com.github.npathai</groupId>
  <artifactId>hamcrest-optional</artifactId>
  <version>2.0.0</version>
  <scope>test</scope>
</dependency>
Physiological answered 1/8, 2019 at 9:11 Comment(0)
D
2

For the moment I have the following information:

  • There is an issue and a feature proposal to support it with othe Java 8 types on hamcrest site.
  • One user created one and posted on his GitHub as an example. Still not on Maven but working on it.
Devotional answered 8/6, 2016 at 17:11 Comment(0)
Y
2

Till this works its way into the Hamcrest, or if you can't add an external library. If you are okay with adding a class, the following does the work for an empty optional

class EmptyOptionalMatcher<T> extends BaseMatcher<Optional<T>> {

    private Optional<T> optionalActual;

    public EmptyOptionalMatcher() {
    }

    @Override
    public boolean matches(Object item) {
        optionalActual = (Optional<T>) item;

        if (optionalActual == null) {
            return false;
        }

        boolean empty = !optionalActual.isPresent();
        return empty;
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("optional is empty");
    }

    @Override
    public void describeMismatch(Object item, Description description) {
        if (optionalActual == null) {
            description.appendText(" optional was NULL?");
        } else {
            description.appendText(" was: " + optionalActual.get());
        }
    }

}

Then have a matchers helper or common class with this static method that you can import and use:

public static <T> Matcher<? super Optional<T>> emptyOptional() {
    return new EmptyOptionalMatcher<>();
}

Usage as:

assertThat(someOptional, is(emptyOptional()));

OR the negative test as

assertThat(someOptional, is(not(emptyOptional())));
Yammer answered 22/6, 2018 at 17:39 Comment(0)
M
1

If you only want to verify that an optional field of some object is present/not present, you can use the following idiom:

Expected object:

public class BusinessObject {
    private Long id;
    private String name;
    private Optional<AnotherObject> anotherObject;
}

Hamcrest test would look like this:

assertThat("BusinessObject is not as expected", businessObject, allOf(
                hasProperty("id", equalTo(1L)),
                hasProperty("name", equalTo("Some title")),
                hasProperty("anotherObject", hasProperty("present", equalTo(true)))
        ));
Mintun answered 23/10, 2019 at 5:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.