Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assert value with assertJ in Optional

I have two classes:

class Outer {
    Inner inner = new Inner("value");
}

class Inner {
   private final String value;
   
   Inner(String value) {
      this.value = value;
   }
}

public Optional<Outer> getOptionalValue() {
   return Optional.of(new Outer());
} 

And my test:

public void testCLass() {
   Assertions.assertThat(getOptionalValue())
      .isPresent()
      .map(v -> v.inner.value)
      .isEqualTo("value");
}
   

I expect it to pass, because isPresent unwraps optional, map converts Outer into value and in the last method I just compare strings.

But it fails on the last line with the message:

Expecting:
 <Optional[value]>
to be equal to:
 <"value">
but was not.

I have no idea why the optional is not unwrapped

like image 702
a3dsfcv Avatar asked Jun 24 '20 20:06

a3dsfcv


1 Answers

The javadoc for OptionalAssert's map method states

Call map on the Optional under test, assertions chained afterwards are performed on the Optional resulting from the map call.

However, isEqualTo is actually comparing the value of the AbstractAssert as a whole. It's not overriden for OptionalAssert to compare the enclosed value. An OptionalAssert's value, the Optional itself, is not equal to a String.

You'll want to use hasValue

Verifies that the actual Optional contains the given value (alias of contains(Object)).

Assertion will pass :

assertThat(Optional.of("something")).hasValue("something");
assertThat(Optional.of(10)).contains(10);

So

Assertions.assertThat(getOptionalValue())
      .isPresent()
      .map(v -> v.inner.value)
      .hasValue("value");

Or, because hasValue actually performs the isPresent check internally, you could just use

Assertions.assertThat(getOptionalValue())
      .map(v -> v.inner.value)
      .hasValue("value");
like image 113
Savior Avatar answered Sep 27 '22 22:09

Savior