Search

Dark theme | Light theme

July 17, 2023

Awesome AssertJ: Writing Assertions For Optional

For a lot of types AssertJ has special assertion methods. Also for the type Optional. If we want to assert an Optional value we can use several methods that AssertJ provides. For example to check if an Optional is present we can use isPresent() or the alias isNotEmpty(). To check if the Optional is empty we can use isEmpty() or the alias isNotPresent(). Checking the value of an Optional (if it is indeed set) can be done with hasValue() or contains(). For more fine grained assertions on the value we can use hasValueSatisfying(Condition) or hasValueSatisfying(Consumer). With the map(Function) and flatMap(Function) methods we can map the Optional, if not empty, to another value and assert that value.

In the following example we see assertion methods for an Optional instance:

package mrhaki;

import org.assertj.core.api.Condition;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.Test;

import java.util.Optional;

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

class OptionalAssertions {
    
    @Test 
    void checkOptionalPresent(){
        assertThat(Optional.of("Awesome AssertJ"))
                // Check if Optional has a value.
                .isPresent()
                
                // Or we use the alias isNotEmpty().
                .isNotEmpty();
    }
    
    @Test 
    void checkOptionalNotPresent() {
        assertThat(Optional.empty())
                // Check if Optional is empty.
                .isEmpty()
                
                // Or we use the aliase isNotPresent().
                .isNotPresent();
    }
    
    @Test
    void checkValueOfOptional() {
        assertThat(Optional.of("Awesome AssertJ"))
                // We can check the value with hasValue(...).
                // We don't have to call get() ourselves.
                .hasValue("Awesome AssertJ")
                
                // Or we use the alias contains(...).
                .contains("Awesome AssertJ");
    }
    @Test
    void checkGetOfOptional() {
        // We can use get() to chain more assertions,
        // but we can only use generic Object assertions.
        assertThat(Optional.of("Awesome AssertJ"))
                .get()
                // We can only use Object assertions.
                .isEqualTo("Awesome AssertJ");

        // If we use get(InstanceOfAssertFactory) we get
        // back an object to use assertion methods for the 
        // given type.
        // The interface InstanceOfAssertFactories has a lot of 
        // useful constants to force the type returned by the Optional,
        // so we can use the assertions for that type.
        assertThat(Optional.of("Awesome AssertJ"))
                .get(InstanceOfAssertFactories.STRING)
                // Now we can use String assertions:
                .startsWith("Awesome")
                .endsWith("AssertJ");
    }

    @Test
    void checkValueSatisfyingOfConditional() {
        // We can use hasValueSatisfying(Consumer)
        // with the instance that is wrapped in the Optional
        // for more fine grained assertion.
        // Also, we can use assertions for the type wrapped
        // in the Optional.
        assertThat(Optional.of("Awesome AssertJ"))
                .hasValueSatisfying(s -> {
                    assertThat(s)
                            .startsWith("Awesome")
                            .endsWith("AssertJ");
                });
    }
    
    @Test
    void checkObjectValueOfOptionalWithCondition() {
        // Record to store properties of a framework.
        record Framework(String name, boolean awesome) {}

        // We can write a Condition that checks if the awesome
        // property is set to true.
        var isAwesomeFramework = new Condition<Framework>(Framework::awesome, "Framework is awesome!");

        // And with hasValueSatisfying we can use the Condition.
        assertThat(Optional.of(new Framework("AssertJ", true)))
                .hasValueSatisfying(isAwesomeFramework);
    }

    @Test
    void checkTransformedValueOfOptional() {
        // We can use map(...) to transform the value
        // of the optional (if present)
        // and write assertions for the transformed value.
        assertThat(Optional.of("Awesome AssertJ"))
                .map(String::toUpperCase)
                .hasValue("AWESOME ASSERTJ");

        // Record to store framework data with an optional type.
        record Framework(String name, Optional<Boolean> awesome) {}
        
        // With flatMap(...) we can transform the value
        // of the optional (if present) to another Optional
        // and write assertions for this transformed Optinal value.
        assertThat(Optional.of(new Framework("Awesome AssertJ", Optional.of(true))))
                .flatMap(Framework::awesome)
                .isPresent()
                .hasValue(true);
    }

    @Test
    void checkInstanceOfOptional() {
        // With containsInstanceOf we can write an assertion
        // to check the type that is contained in the Optional.
        assertThat(Optional.of("Awesome AssertJ"))
                .containsInstanceOf(String.class);
    }
}

Written with AssertJ 3.24.2.