Skip to content

Add map(…) and flatMap(…) to OptionalAssert  #751

@odrotbohm

Description

@odrotbohm

Summary

If you're dealing with Optionals whose values return Optionals, you end u with a lot of nesting. It would be cool if these could be flattened out like this:

Example

Optiona<Foo> foo = Optional.of(foo);

assertThat(foo).hasValueSatisfying(it -> {
  assertThat(it.methodReturningAnOptional()).hasValueSatisfying(inner -> {
    assertThat(inner.methodReturningNoOptional()).isEqualTo(reference);
  }
}

Note, how you constantly have to nest expressions and also rewrap the values obtained from the method call into new asserts.

It would be cool if one could rather write this instead:

assertThat(foo)
  .flatMap(it -> it.methodReturningAnOptional())
  .map(it -> it.methodReturningNoOptional())
  .isEqualTo(reference);

I currently have this custom assert class in my code to achieve this:

public class OptionalAssert<T> extends AbstractAssert<OptionalAssert<T>, Optional<T>> {

  public OptionalAssert(Optional<T> actual) {
    super(actual, OptionalAssert.class);
  }

  public static <T> OptionalAssert<T> optionalAssertThat(Optional<T> optional) {
    return new OptionalAssert<T>(optional);
  }

  public <S> OptionalAssert<S> flatMap(Function<T, Optional<S>> function) {

    Assertions.assertThat(actual).isPresent();

    return optionalAssertThat(actual.flatMap(function));
  }

  public <S> AbstractObjectAssert<?, S> map(Function<T, S> function) {

    Assertions.assertThat(actual).isPresent();

    return Assertions.assertThat(actual.map(function).orElseThrow(() -> new IllegalStateException()));
  }
}

I guess that can be improved to report good error messages in case of a flat map step producing an empty Optional, but it does the trick for me now.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions