@Test
  void with() {
    assertExpressional(person.with(c -> c.fullName.is("John")),
            "call op=EQUAL path=fullName constant=John");
    assertExpressional(person.with(c -> c.fullName.is("John").nickName.isPresent()),
            "call op=AND",
            "  call op=EQUAL path=fullName constant=John",
            "  call op=IS_PRESENT path=nickName");
    assertExpressional(person.fullName.with(f -> f.is("John")),
            "call op=EQUAL path=fullName constant=John");

    assertExpressional(person.bestFriend.value().with(f -> f.hobby.is("aaa")),
            "call op=EQUAL path=bestFriend.hobby constant=aaa");

    assertExpressional(person.bestFriend.value().hobby.with(h -> h.is("a").is("b")),
            "call op=AND",
            "  call op=EQUAL path=bestFriend.hobby constant=a",
            "  call op=EQUAL path=bestFriend.hobby constant=b");

    assertExpressional(person.bestFriend.value().hobby.with(h -> h.is("a").is("b")),
            "call op=AND",
            "  call op=EQUAL path=bestFriend.hobby constant=a",
            "  call op=EQUAL path=bestFriend.hobby constant=b");

    assertExpressional(person.bestFriend.value().hobby.with(h -> h.is("a").is("b"))
                   .fullName.isEmpty(),
            "call op=AND",
            "  call op=EQUAL path=bestFriend.hobby constant=a",
            "  call op=EQUAL path=bestFriend.hobby constant=b",
            "  call op=EQUAL path=fullName constant=");

    assertExpressional(PersonCriteria.person
                    .fullName.with(StringMatcher::isEmpty)
                    .or()
                    .fullName.with(StringMatcher::notEmpty),
            "call op=OR",
            "  call op=EQUAL path=fullName constant=",
            "  call op=NOT_EQUAL path=fullName constant="
    );

    assertExpressional(PersonCriteria.person
                    .fullName.with(StringMatcher::isEmpty)
                    .fullName.with(StringMatcher::notEmpty),
            "call op=AND",
            "  call op=EQUAL path=fullName constant=",
            "  call op=NOT_EQUAL path=fullName constant="
    );

    assertExpressional(PersonCriteria.person.age.atLeast(21).with(p -> p.isActive.isTrue()),
            "call op=AND",
            "  call op=GREATER_THAN_OR_EQUAL path=age constant=21",
            "  call op=EQUAL path=isActive constant=true");

    assertExpressional(PersonCriteria.person.with(p -> p.isActive.isTrue()).with(p -> p.fullName.is("a")),
            "call op=AND",
            "  call op=EQUAL path=isActive constant=true",
            "  call op=EQUAL path=fullName constant=a");
  }
Tests that expression is built correctly by "serializing" it to string.
It is easier to debug expression when it is presented as human-readable tree
criteria/common/test/org/immutables/criteria/ExpressionAsStringTest.java