Microservices and Consumer Driven Contract testing using Pact

Background

As per the current trends, Microservice Architecture has become a common paradigm using which enterprise applications are built. With this paradigm shift, an application is going to have myriad set of independent and autonomous (micro)services. So how does a developer do testing within Microservice Architecture? Answer is very obvious –

  1. Create integration tests that invokes microservice under test which will internally call dependent microservices
  2. Get all the services under test up and running
  3. Start executing integration test which invokes microservice under test

With this approach, the entire developer level integration testing will have following disadvantages –

  • Extremely slow execution of integration tests
  • Fragile tests as they are directly dependent on successful execution of other micorservices
  • Obscures ability to debug outcome of tests as it will be ambiguous
  • Combinatorial increase in number of tests (depending on number of classes and alternate paths within them)

And hence the overall intent behind having integration tests gets defeated.

So Martin Fowler gave an interesting perspective called Consumer Driven Contract which is nothing but a contract between consumer of service and producer of service. In this style of testing, format of contract is defined by Consumer and then shared with the corresponding Producer of service.

Lets take an example to understand this. We have ReservationClient which is an end consumer facing API; this in turn invokes ReservationService which is responsible for managing business workflows pertaining to Reservation. For the sake of simplicity, we will just try to retrieve Reservation using both the services.

Pact

We will be using Pact for realizing Consumer Driven Contract (CDC) testing. PACT is an open source CDC testing framework which also supports multiple languages like Ruby, Java, Scala, .NET, Javascript, Swift/Objective-C. It comprises of 2 main steps for performing CDC testing. One may want to look at the jargons to understand Pact specific terminology

  1. Pact generation on consumer side service
  2. Pact verification on provider side service

1. Pact Generation on Consumer side

1.1 Define expected result

We first start by writing JUnit test case TestReservationClient for ReservationClient, where we specify the expected result from the Provider i.e. ReservationService. Test case can be implemented in 2 ways –

  1. Extend the base class ConsumerPactTest
  2. Use annotations

We will be implementing test case using second approach.

 

1.2 Generate the Pact file

Lets run the test case after implementing test case with required Pact contracts. If the test runs successfully, a JSON file will be created within a new folder pacts underneath /target folder

1.3 Share the generated pact file with Producer

Last step of consumer should be to share the generated contract with provider. This can be done either by a file sharing service or Pact Broker

2. Pact Verification on Provider side

2.1 Bootstrap the Provider service

After getting the pact file from consumer, provider service i.e. ReservationServiceController should be bootstrapped first

2.2 Execute JUnit-Pact test against the

Implement a JUnit test which will refer to the pact file and also match its state with that of the state configured at Consumer’s end

2.3 Check verification result

After executing verification test by Provider JUnit i.e. ReservationServiceControllerContractTest we get the output as shown below

Lets understand the nature of output in case contract fails. Lets create a separate JUnit for ReservationClient which returns user’s name along with its id. We then follow the same steps as mentioned above and then verify the generated pact with Provider’s JUnit test case. Resulting output is as shown below

It is quiet evident from the above error that Consumer has broken the contract as it is sending id attribute of user.

Summary

As we saw above, with CDC we can make integration testing easy to manage and strive to get faster feedback. This in a way helps us to realize Test Pyramid. In subsequent posts, I will try to introduce usage of Spring Cloud Contract for realizing CDC testing.

Github code for your perusal.

 

 

 

Leave a Reply