36

Having a POJO such as:

public class ClientWebRequest {

    private URI uri;
    private HttpMethod httpMethod;

    private final Header header;
    private final Body body;


    public ClientWebRequest(){
        header = new Header();
        body = new Body();
    }

    //getters and setters
}

About JUnit working with AssertJ the following is valid, the @Test method pass:

assertThat(clientWebRequest).isNotNull();
assertThat(clientWebRequest.getHeader()).isNotNull();
assertThat(clientWebRequest.getHeader().getAccept()).isNotNull();
assertThat(clientWebRequest.getHeader().getAcceptLanguage()).isNull();
assertThat(clientWebRequest.getHeader().getContentType()).isNull();
assertThat(clientWebRequest.getBody()).isNotNull();
assertThat(clientWebRequest.getBody().getBody()).isNull();

Even when it works, is verbose in some way.

I want to know if is possible rewrite all the above in just one sentence, checking each nested property/field. Thus I have tried for example the following:

assertThat(clientWebRequest.getHeader()).isNotNull()
        .hasFieldOrProperty("accept").isNotNull()
        .hasFieldOrProperty("acceptLanguage").isNull();

But fails with the following error message:

org.junit.ComparisonFailure: expected:<null> 
but was:<Header [accept=[application/json;charset=UTF-8], acceptLanguage=null, contentType=null]>
        at

My main goal is workaround with isNotNull and isNull for each property/field of the POJO

Alpha: Thanks to Joel's suggestion the following works now:

assertThat(clientWebRequest).isNotNull()
                            .extracting("header.accept")
                            .doesNotContainNull();

assertThat(clientWebRequest).isNotNull()
        .extracting("header.acceptLanguage", "header.contentType")
       .containsNull();

From above (two blocks) If I try the following (one block):

assertThat(clientWebRequest).isNotNull()
                            .extracting("header.accept")
                            .doesNotContainNull();
       .extracting("header.acceptLanguage", "header.contentType")
       .containsNull();

It fails. Just curious if is possible apply one block.

djm.im
  • 3,295
  • 4
  • 30
  • 45
Manuel Jordan
  • 15,253
  • 21
  • 95
  • 158

1 Answers1

64

I think the best way is to extract all the properties/fields and then checks it does not contain null.

Example:

TolkienCharacter frodo = new TolkienCharacter("Frodo", 33, HOBBIT);

// support nested properties: 
assertThat(frodo).extracting("name", "age", "race.name")
                 .doesNotContainNull()
                 .containsExactly("Frodo", 33, "Hobbit");

Note that you can also use lambdas to extract values from the object under test.

assertThat(frodo).extracting(TolkienCharacter::getName,
                             character -> character.age,
                             character -> character.getRace().getName())
                 .containsExactly("Frodo", 33, "Hobbit");
Joel Costigliola
  • 6,308
  • 27
  • 35
  • Thanks, please see the Alpha section added. Not sure if one block is possible. – Manuel Jordan Dec 26 '17 at 14:16
  • 2
    That won't work because after applying `extracting` you end up performing assertions on the collection of values corresponding to the extracted properties. If you use `extracting` again it will try to extract properties from each elements of the previous collection of values. – Joel Costigliola Dec 26 '17 at 20:47
  • 1
    what will happen if `character.getRace()` is null, wouldn't the test case blow up with NullPointerException? – Govinda Sakhare Jan 14 '21 at 16:20
  • For Kotlin users the last line of the first example will look like: `.containsExactly(Tuple("Frodo", 33, "Hobbit"))` – DavidR Feb 02 '22 at 18:43