Assert value with assertJ in Optional
Asked Answered
M

3

26

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

Mondrian answered 24/6, 2020 at 20:11 Comment(2)
I think also you have a typo .map(v -> v.inner.value) I think you are using getter to access to the valueIrradiate
@YCF_L this particular example is without getterMondrian
W
53

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");
Waneta answered 24/6, 2020 at 20:30 Comment(0)
I
4

You are missing a step, you should to use get() to get the value of the Optional, because map in your case, returns an Optional<String> and not a String:

.map(v -> v.inner.getValue())
.get()
.isEqualTo("value");

Or if you want to stick with the Optional, you should to compare with an Optional:

.map(v -> v.inner.getValue())
.isEqualTo(Optional.of("value"));
Irradiate answered 24/6, 2020 at 20:17 Comment(2)
Is there any explanation to this? Why has it wrapped outer.inner.value into Optional?Mondrian
@Mondrian I state it in my answer, map return an Optional, in your case an Optional of String because v.inner.getValue() is a StringIrradiate
B
1

If you can, make the test directly on the received Optional rather than taking it apart and testing three levels deep.

    Assertions.assertThat(getOptionalValue()).hasValue(new Outer());

It’s clear and simple, it’s the recommended way, and if Outer and Inner have appropriate equals methods, you need nothing more. While I haven’t tried it with AssertJ myself, I believe that it gives clear messages both in the case where the Optional is empty and in the case where it holds an incorrect value at some level.

Bondsman answered 25/6, 2020 at 3:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.