Search code examples
javajsonobjectpactcontract

How to use PactDslJsonBody for an object within an object


Trying to implement Contract Testing using Pact. I'm starting off with Consumer side right now. It is event-driven messages so I am using MessagePactBuilder

I will give an example of what I have and what I'm trying to achieve.

What I currently have:

@Pact
public MessagePact validMessage(MessagePactBuilder builder){
 PactDslJsonBody body = new PactDslJsonBody();

 body.object("student")
     .stringType("studentFirstName")
     .stringType("studentLastName")
     .stringType("studentAddress") // I understand this won't work. 

 Map<String, String> metadata = new HashMap<String, String>();
 metadata.put("contentType", "application/json");

 return builder
        .given("validMessage")
        .expectsToReceive()
        .withMetadata(metadata)
        .withContent(body)
        .toPact();
}

The issue I have is the student class is composed of

String studentFirstName
String studentLastName
Address studentAddress

So you can see that it is also taking in an Address object. The Address object consists of all strings

String addressLine
String city
String state
String zip

Any ideas on how I can create the PactDslJsonBody this way? Or if I need to implement it another way? Any ideas would be appreciated.


Solution

  • You can find some examples at https://docs.pact.io/implementation_guides/jvm/consumer#examples

    In your case, using the PactDslJsonBody, it would look like the following:

    body
      .object("student")
        .stringType("studentFirstName")
        .stringType("studentLastName") 
        .object("studentAddress") 
          .stringType("adressLine")
          .stringType("city")
          // Others...
        .closeObject()
      .closeObject()
    

    (False indentation to match the JSON structure)

    This can become very verbose and hard to read because of missing indentation. That's why there's an alternative syntax using LambdaDsl:

    newJsonBody((o) -> {
        o.object("student", (s) -> {
          s.stringType("studentFirstName");
          s.object("studentAddress", (a) -> {
            a.stringType("adressLine");
            // Others...
          });
          // Others...
        });
    })
    .build();
    

    This syntax naturally looks' like the JSON structure even though it's still quite verbose.

    If you want less verbose syntax, only alternative is to use Kotlin or Scala.