@Test
  void with2() {
    // nested
    assertExpressional(person.with(p1 -> p1.with(p2-> p2.fullName.is("a"))),
            "call op=EQUAL path=fullName constant=a");

    assertExpressional(PersonCriteria.person.with(p1 -> p1.with(p2-> p2.fullName.is("a")).age.is(11)),
            "call op=AND",
            "  call op=EQUAL path=fullName constant=a",
            "  call op=EQUAL path=age constant=11");

    assertExpressional(PersonCriteria.person.age.is(11).with(p1 -> p1.with(p2-> p2.nickName.is("a"))),
            "call op=AND",
            "  call op=EQUAL path=age constant=11",
            "  call op=EQUAL path=nickName constant=a"
            );

    assertExpressional(PersonCriteria.person.bestFriend.value().hobby.is("aaa")
                    .with(p1 -> p1.age.is(22).with(p2-> p2.bestFriend.value().hobby.is("bbb"))),
            "call op=AND",
            "  call op=EQUAL path=bestFriend.hobby constant=aaa",
            "  call op=AND",
            "    call op=EQUAL path=age constant=22",
            "    call op=EQUAL path=bestFriend.hobby constant=bbb"
            );

    assertExpressional(PersonCriteria.person.with(p1 -> p1.with(p2-> p2.with(p3 -> p3.fullName.is("a")))),
            "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