<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Alexander Potukar (E.ON-Devs)</title>
    <description>The latest articles on Forem by Alexander Potukar (E.ON-Devs) (@apotukareon).</description>
    <link>https://forem.com/apotukareon</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F325093%2Fed7e9174-8373-4f30-8ee5-b7bb2ec76bd5.png</url>
      <title>Forem: Alexander Potukar (E.ON-Devs)</title>
      <link>https://forem.com/apotukareon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/apotukareon"/>
    <language>en</language>
    <item>
      <title>Shared Code in Microservices? Domain Driven Design to the Rescue</title>
      <dc:creator>Alexander Potukar (E.ON-Devs)</dc:creator>
      <pubDate>Tue, 04 Feb 2020 12:43:39 +0000</pubDate>
      <link>https://forem.com/eon/shared-code-in-microservices-domain-driven-design-to-the-rescue-1i44</link>
      <guid>https://forem.com/eon/shared-code-in-microservices-domain-driven-design-to-the-rescue-1i44</guid>
      <description>&lt;p&gt;Microservices have been around for a while so they are state-of-the-art rather than just a hype. Countless blog articles, books, best practices, tweets and war stories from concrete projects testify to a living architectural style. There is hardly a question that has not been repeatedly examined from all sides: starting with the basic concept and the technical layout, to topics such as team and communication structure, deployment, service discovery, logging and monitoring, there are enough instructions, frameworks, tools, and literature. Therefore this article is not intended as another comprehensive introduction to microservices.&lt;/p&gt;

&lt;p&gt;This blog post is rather about a topic that comes up again and again and that concerns conference pundits as well as developers in the verbal fights in the coffee kitchen: Is it reasonable to reuse code in microservice projects? Is shared code, in whatever form, a brutal violation of the isolation principle? Or does &lt;strong&gt;Don't Repeat Yourself&lt;/strong&gt; (DRY-principle) also apply here? After briefly touching upon the principle of loose coupling and isolation we will discuss the traditional promise of reusability, its flipside, and the meaning of &lt;strong&gt;Bounded Context&lt;/strong&gt; in the realm of &lt;strong&gt;Domain-Driven Design&lt;/strong&gt;* (DDD). Afterwards we will delve into examples where it is perfectly legitimate to share code in microservices including some edge cases and how to deal with them. Finally we will discuss shared &lt;strong&gt;Infrastructure as Code&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Loose Coupling and Isolation
&lt;/h2&gt;

&lt;p&gt;Microservices should not be an end in themselves. One of the core goals in the introduction of microservices is decoupling of components that are designed and implemented under technological autonomy, communicating via interfaces. The purpose is to manage complexity in an effective way, to provide a higher degree of isolation during the application runtime and the to test business ideas and technologies faster (and to throw them away if they prove to be unsuitable).&lt;/p&gt;

&lt;p&gt;A microservice typically implements the business process of a specialist domain, it maintains and changes its own locally valid data, it is responsible for its management and exposes explicit interfaces. So it is "reasonably small" and focuses on a specific task. This strict modularization concept and the division of the teams into domain components result in several other advantages [1][2].&lt;/p&gt;

&lt;p&gt;But even in microservice projects, there is often a desire for shared use of database schemas, data sources, code for access to frequently used objects in a domain or existing functionality. There are two forces working in different directions at one point: the “maximum generic reusability” on the one hand, the concept of independence and isolation on the other.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reusability as the Promise of Salvation?
&lt;/h2&gt;

&lt;p&gt;The strong desire for reusability is not surprising as the DRY-principle has been the mantra of software development for decades. And even today developers are being instilled, redundancy is the worst of all developer villains, after all it would make more sense to "inherit" code instead of writing. What can be reused does not have to be rewritten and thus reduces costs. Reusable code should ideally meet the following requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Must fit in many cases&lt;/li&gt;
&lt;li&gt;High quality&lt;/li&gt;
&lt;li&gt;Good documentation &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Developers commonly argue that the disclosure of such code in an open source project automatically fulfills the requirements described above as external contributions and bug reports lead to an improvement in the code. Publication as an open source library actually makes sense, after all, you don't want to use code that you wouldn't be willing to distribute to external users. But even if it makes it more difficult for things that are too specific to infiltrate into such a shared project, one crucial question remains unanswered: Where exactly is the boundary between sensible code sharing and excessive generalization?&lt;/p&gt;

&lt;p&gt;Answers to this are provided by the concept of &lt;strong&gt;Bounded Context&lt;/strong&gt; from &lt;strong&gt;DDD&lt;/strong&gt;, an approach to software modeling that focuses very strongly on the business of an application domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bounded Context!
&lt;/h2&gt;

&lt;p&gt;The urge to generalize everything has led to global data models and wrong technical abstraction in many past projects. Instead of promised productivity boosts, this procedure slows down the development process. The reason for this is obvious: A technically incorrect generalization leads to a high coordination effort, since many developers involved have to coordinate with each other. Finally, it has to be decided which code ends up in a shared component and how its quality is ensured. In extreme cases you end up with an entire organization that is dedicated to “cross-sectional tasks” as guardian of the holy grail of reusability which is not customer facing and slows down delivery of software [3].&lt;/p&gt;

&lt;p&gt;In contrast, the concept of bounded context is central to DDD. Each domain usually consists of several bounded contexts. Such a “context boundary” describes the scope of a technical model.&lt;/p&gt;

&lt;p&gt;Let's give a simple example: The term &lt;strong&gt;flight&lt;/strong&gt; from the aviation industry has several specific meanings, depending on the context. From a passenger's perspective, a flight is the transportation of people to a destination airport, either in the form of a direct flight or with a stopover. From the point of view of the on-board personnel, a flight consists of take-off and landing. And airport maintenance technicians look at a flight from the position of aircraft maintenance. Depending on the context, this term means something different.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0NJzrsEa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/eon-com/shared-code-in-microservices/master/images/flight.png%3Fversion%3D1580820033" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0NJzrsEa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/eon-com/shared-code-in-microservices/master/images/flight.png%3Fversion%3D1580820033" alt="Image displaying concept of a flight from perspective of different businesses"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Modeling a flight in the form of a generic flight class would only lead to confusion. Individual cases should be modeled in their own bounded contexts. Attempting to outsource similarities and common features to a parent class and to implement individual characteristics in child classes inevitably leads to strong coupling [4].&lt;/p&gt;

&lt;p&gt;A rule of thumb:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duplication is better than false abstraction&lt;/li&gt;
&lt;li&gt;Redundancies should be consciously accepted if the alternative is a strong coupling&lt;/li&gt;
&lt;li&gt;No reuse of business logic across multiple bounded contexts &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code reuse for code within a bounded context, however, is not critical.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cross-cutting Concerns
&lt;/h2&gt;

&lt;p&gt;What about libraries like Apache Commons or Google Guava? Should I avoid using them to stick with true microservices doctrine? Of course not! Shared libraries for technical issues such as logging, monitoring, tracing, string manipulation, collections or abstraction layers for infrastructure access are cross-cutting concerns, as they do not depend on the context of a domain. It is perfectly okay to share libraries that involve non-technical aspects [5].&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependency Hell
&lt;/h3&gt;

&lt;p&gt;However, this answer does not address the problem that such libraries often have the disadvantage of many transitive dependencies. It is only a matter of time before you catch version conflicts and it is not uncommon to end up in the notorious &lt;strong&gt;Dependency Hell&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One way to avoid the dependency hell problem is to provide very lean libraries for clearly defined tasks with little or no dependency. Such libraries are in stark contrast to general-purpose libraries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment Dependencies
&lt;/h3&gt;

&lt;p&gt;The following scenario, which originates from a real project, is somewhat more complex: A library for health checks verifies, among other things, the connection to Elasticsearch and the existence of certain indices and aliases. Under the hood, this library uses an open source library that provides an Elasticsearch client. In the context of a user story, new features have been added to the health check library. At the same time there was an upgrade to a new major version [6] of the Elasticsearch client which led to a significant extra effort.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9BxAetbZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/eon-com/shared-code-in-microservices/master/images/deps.png%3Fversion%3D1580820033" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9BxAetbZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/eon-com/shared-code-in-microservices/master/images/deps.png%3Fversion%3D1580820033" alt="Image displaying dependency version conflicts"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But how? In our specific example, services that use the new health checks also use the same Elasticsearch client in their own (technical) code, only in an older version. The increased effort was due to adjustments in the concerned services. To avoid such a situation there are two possible solutions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replacement of the Elasticsearch client in the health checks with a lightweight solution (checking the connection etc. does not need all the features of a comprehensive Elasticsearch client)&lt;/li&gt;
&lt;li&gt;(Temporary) provision of the Health Check Library in two versions: one with the old and one with the new version of the Elasticsearch client &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first glance, both approaches seem like unnecessary trouble. However, with several dozen services, this effort prevents extensive "forced upgrades", the inclusion of the new health checks can be done gradually service by service.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shared Service
&lt;/h3&gt;

&lt;p&gt;The following scenario goes in a similar direction: Assume that a shared library is provided for the use of a central service. If changes are made to this service, all microservices would have to use an updated version of this library. If the services in question are managed by different teams, this entails a considerable coordination effort in redeployment.&lt;/p&gt;

&lt;p&gt;Backward-compatible changes to the service, on the other hand, do not result in deployment dependencies, since older versions of this library are still functional. Temporary provision of two different versions of the service including two different library versions is also a conceivable solution. The older variant is then switched off as soon as it is ensured that no client is dependent on it anymore.&lt;/p&gt;

&lt;p&gt;Generally speaking, in the case of external dependencies in a microservice, the freedom of choice of the specific version of a library used should always be ensured in order to avoid dependencies of this kind.&lt;/p&gt;

&lt;h2&gt;
  
  
  DDD Context Maps and Shared Kernel
&lt;/h2&gt;

&lt;p&gt;In DDD every bounded context has its own &lt;strong&gt;Ubiqituous Language&lt;/strong&gt; [7]. One of the features of DDD is &lt;strong&gt;Context Maps&lt;/strong&gt;, which allows grasping the different relationships and translations between bounded contexts, their models and team-wide languages. To explain all kinds of context maps would go beyond the scope of the discussion, so we limit ourselves to a use case in which areas of the domain model are shared between different teams and hence different bounded contexts: &lt;strong&gt;Shared Kernel&lt;/strong&gt;. Sometimes it's valid that two teams share common structures; this applies in particular if they are subject to frequent changes. Instead of multiple implementations with inconsistencies a small part of the data model (intersection of two bounded contexts) can be shared between different teams.&lt;/p&gt;

&lt;p&gt;Of course, this procedure contradicts the principles of loose coupling and isolation mentioned above, because the independence between microservices is lost. This procedure is a trade-off and needs to be weighed up in line with usage. &lt;strong&gt;It should not be used as a justification for a universal data model in a complex application landscape!&lt;/strong&gt; Nevertheless, there are scenarios such as session or authentication logic, where such a procedure is appropriate.&lt;/p&gt;

&lt;p&gt;A shared kernel is often difficult to create and to maintain, because you have to achieve open communication between the teams and permanent agreement on what belongs to the shared model. It requires a healthy communication culture between the teams involved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shared Infrastructure as Code
&lt;/h2&gt;

&lt;p&gt;For the sake of an healthy and productive team autonomy and to avoid infrastructure monoliths, it is recommended to divide &lt;strong&gt;Infrastructure as Code&lt;/strong&gt; artifacts according to macroarchitecture and microarchitecture aspects. All infrastructure definitions that belong directly to a certain domain/bounded context should be part of the respective microservice. Let's give an example to illustrate this: A microservice that installs data and then stores it in a message queue should include the infrastructure definition of the topic of the message queue. The subscriptions of the queue, on the other hand, should be defined in services, which consume data from this topic.&lt;/p&gt;

&lt;p&gt;All infrastructure definitions that cannot be clearly assigned to a certain service are aspirants for the macro infrastructure (or macro stack). So this stack contains all cross-cutting aspects and ideally consists exclusively of definitions which rarely change. This typically includes network and security infrastructure [8]. The division into various service stacks (micro-stacks) and macro-stacks can be implemented, for example, using the modularization and inclusion concepts of Terraform and CloudFormationn [9].&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Shared code or code reuse in microservices leads to dependencies, which can lead the core idea of ​​this architecture style to absurdity. Therefore, one should orientate oneself on the idea of ​​the bounded context of domain driven design and differentiate between technical and non-technical aspects. The latter can be converted into shared code. However, it is recommended to keep it lean and to ensure that it is backwards compatible when changes are made to avoid deployment dependencies. The &lt;strong&gt;Shared Kernel&lt;/strong&gt; pattern should be used with care and also requires a healthy communication culture between the teams. Infrastructure as code is to be assessed from a similar point of view as program code.&lt;/p&gt;




&lt;p&gt;[1] See also &lt;a href="http://www.informit.com/articles/article.aspx?p=2738465&amp;amp;seqNum=2"&gt;http://www.informit.com/articles/article.aspx?p=2738465&amp;amp;seqNum=2&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[2] Major benefits of microservices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Independent release and deployment of the services (while maintaining backward compatibility of interfaces)&lt;/li&gt;
&lt;li&gt;Separate life cycles&lt;/li&gt;
&lt;li&gt;Scaling according to needs&lt;/li&gt;
&lt;li&gt;Greater technological independence, since ideally there are no direct dependencies on other microservices&lt;/li&gt;
&lt;li&gt;Fast local decisions on technical and micro-architectural questions by autonomous teams&lt;/li&gt;
&lt;li&gt;Less coordination effort between the different teams&lt;/li&gt;
&lt;li&gt;Freedom of choice of technology (languages, frameworks), thereby greater team commitment (however, this freedom of choice is often restricted in practice in order to avoid a technology zoo)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;[3] See also &lt;a href="https://medium.com/ingeniouslysimple/context-mapping-in-domain-driven-design-9063465d2eb8"&gt;https://medium.com/ingeniouslysimple/context-mapping-in-domain-driven-design-9063465d2eb8&lt;/a&gt;&lt;br&gt;
[4] In addition, the flexibility achieved when focusing on reusability also leads to an increase in complexity. One also speaks of the use / reuse paradox: &lt;a href="http://techdistrict.kirkk.com/2009/10/07/the-usereuse-paradox/"&gt;http://techdistrict.kirkk.com/2009/10/07/the-usereuse-paradox/&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
[5] The statement applies not only to microservices projects, but generally wherever you want to modularize sensibly. In addition, changes to the base class will quickly violate the Liskov substitution principle: &lt;a href="http://newsight.de/2015/01/07/das-liskov-substitution-principle"&gt;http://newsight.de/2015/01/07/das-liskov-substitution-principle&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
[6] We limit ourselves to Java in this scenario, but the statements made here also apply to other languages.&lt;br&gt;&lt;br&gt;
[7] See &lt;a href="https://martinfowler.com/bliki/UbiquitousLanguage.html"&gt;https://martinfowler.com/bliki/UbiquitousLanguage.html&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[8] Semantic versioning: &lt;a href="https://semver.org/"&gt;https://semver.org/&lt;/a&gt; &lt;br&gt;
[9] See &lt;a href="https://www.infoq.com/news/2018/06/cloud-native-continuous-delivery"&gt;https://www.infoq.com/news/2018/06/cloud-native-continuous-delivery&lt;/a&gt; &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Consumer-driven Contract Testing with Pact</title>
      <dc:creator>Alexander Potukar (E.ON-Devs)</dc:creator>
      <pubDate>Mon, 03 Feb 2020 12:30:03 +0000</pubDate>
      <link>https://forem.com/eon/consumer-driven-contract-testing-with-pact-2aed</link>
      <guid>https://forem.com/eon/consumer-driven-contract-testing-with-pact-2aed</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When deploying microservices or any other distributed system, one has to deal with a multitude of interfaces between the single services in place. Classical end-to-end tests require a test environment providing all services at the same time. However, testing HTTP/REST communication between these services can quickly turn into tedious work if one of the involved systems changes. This “expensive” testing strategy is reasonable for entire flows, but is not the best way for API-focussed tests where one consumer expects a specific response from one producer. This is where consumer-driven contract tests come into play: interactions between services are tested more independently in a decoupled fashion. It does not entirely replace end-to-end tests, but it will speed up development for APIs as it focusses on interactions between consumers and producers.&lt;/p&gt;

&lt;p&gt;This blog post will illuminate the concept of consumer-driven contract tests. After discussing topics like test pyramid, naming test types and the core mechanism behind Pact including common questions, we will introduce an example with Pact for JUnit 5 to showcase the basic test setup in JVM based environments. The closing section will briefly deal with the advantages and disadvantages of Pact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why consumer-driven tests?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Test Pyramid
&lt;/h3&gt;

&lt;p&gt;Before delving into consumer-driven tests with Pact, we first should clarify why we might need them. This question can be answered by taking a short look at the “test pyramid”. This term is a metaphor that tells us how to group tests into various buckets with different granularity.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://martinfowler.com/articles/practical-test-pyramid.html" rel="noopener noreferrer"&gt;original concept&lt;/a&gt; coined by &lt;a href="https://en.wikipedia.org/wiki/Mike_Cohn" rel="noopener noreferrer"&gt;Mike Cohn&lt;/a&gt; there were basically three layers from bottom to top: UI tests, service tests and unit tests. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Feon-com%2Ftoyapp-pact-demo%2Fmaster%2Fimages%2FPyramid_1.png%3Fversion%3D1581535215" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Feon-com%2Ftoyapp-pact-demo%2Fmaster%2Fimages%2FPyramid_1.png%3Fversion%3D1581535215" alt="Image displaying original test pyramid"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unit tests ideally run for a short time and provide a high degree of isolation. Interactions with other units are usually mimicked by using test doubles such as fakes, mocks and stubs &lt;sup&gt;1&lt;/sup&gt;. As they can be easily automated without complex infrastructure, they form the basis of any test strategy and cover a large part of the source code. In contrast to that, service tests require a more elaborate set-up than unit tests as different components must be brought into a condition suitable for testing interactions and integrative aspects. e.g. if a database is tested, it must be filled with appropriate test data first. In addition, these tests are more vulnerable to unforseen test failures because they are affected by code changes in more than one component. UI tests verify if the user interface of your application works correctly: User input should trigger the right actions and data should be presented to the user.&lt;/p&gt;

&lt;p&gt;Things have changed a bit since the first concept of the test pyramid. Back then tools like &lt;a href="https://www.seleniumhq.org/" rel="noopener noreferrer"&gt;Selenium&lt;/a&gt; were used for both testing user interfaces and end-to-end integration. Today the term "UI test" is often used in a very broad sense so it also covers UI component tests and UI application tests with mocked backends. Actually UI applications have their own test pyramid.&lt;/p&gt;

&lt;p&gt;Beyond that system tests are often subdivided into integration tests, contract tests and component tests. Beware of confusion: There is no standardized wording for the different test types so you cannot rely on a common understanding of terminology. Some say these kinds of (system) tests are all integration tests, some say they are all component tests. Either way the terms sometimes conflate. Software engineers will argue endlessly about wording and definitions and often this tedious discussion is a big source of confusion &lt;sup&gt;2&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Thus, the boundaries between different test categories are fluent and it is perfectly okay to use your own terminology. But make sure that everyone has the same understanding in your company unit. The following, more detailed pyramid offers a taxonomy as a starting point for your own terminology.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Feon-com%2Ftoyapp-pact-demo%2Fmaster%2Fimages%2FPyramid_2.png%3Fversion%3D1581535215" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Feon-com%2Ftoyapp-pact-demo%2Fmaster%2Fimages%2FPyramid_2.png%3Fversion%3D1581535215" alt="Image displaying more elaborate test pyramid"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  End-to-end tests and when to avoid them
&lt;/h3&gt;

&lt;p&gt;End-to-end tests assume a real application on a fully functional test system. They give you the biggest confidence when to decide if your software is working or not as they simulate a real user better than other test types. However, one buys the benefits of end-to-end testing at a high price as the set-up is much more complex than that of integration or unit tests as it requires a complete system in which each and every service runs with the associated database.&lt;/p&gt;

&lt;p&gt;In a distributed architecture a high degree of automation is required, so setting up a working full environment might be demanding but it has to be done anyway. However, one goal of CI is that changes to the code are checked promptly, indicating whether the changes have led to errors or not. Starting a complete test environment for end-to-end tests leads to longer execution times. Therefore it is not desirable to run fully fledged end-to-end tests for every code change. For example, when you use the Gitflow feature branch model, each change in every feature branch in each service would require a separate test environment in a fashion that they don't get in each other's way. Having said that, end-to-end tests make perfect sense for certain scenarios but not for changed API call responses where quick feedback is desired.&lt;/p&gt;

&lt;h3&gt;
  
  
  The limits of integration tests
&lt;/h3&gt;

&lt;p&gt;Of course one can think of setting up a test environment with one consumer talking to one producer. However, the producer might be dependent on other services and providing a complete working environment is exactly what we want to avoid (integration tests degenerate into full-blown end-to-end tests). Apart from that the producer might not be under control of the team building the test. So one thing you can do is to mock the producer and validate the consumer against the mocked endpoints using a framework such as &lt;a href="http://rest-assured.io/" rel="noopener noreferrer"&gt;REST-assured&lt;/a&gt;. At first glance this approach is valid as it mitigates the pain of waiting for desired changes on the producer's side: We can add e.g. an additional field in the desired response by changing the mock implementation and swiftly go on implementing changes in the consumer. However, the desired changes for the producer have to be communicated. When executing the real end-to-end test this test might break as there is no guarantee if and when the change request is implemented in the producer. And if the end-to-end test does not cover the required change, the build-wall remains green, but then the software is deployed and finally the system in production will fail &lt;sup&gt;3&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;So this is where consumer-driven contract tests come to the scene: they provide a mock producer (called mock provider), facilitate change requests between teams and make sure that a consumer can only be deployed when the changes necessary are implemented in the producer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Pact concepts
&lt;/h2&gt;

&lt;p&gt;Pact is the standard framework for consumer-driven contract testing. Besides JVM languages such as Java, Kotlin, and Scala (all via JUnit) there are also implementations for JavaScript, Python, Go, Swift, .NET, and Ruby.&lt;/p&gt;

&lt;h3&gt;
  
  
  Terminology
&lt;/h3&gt;

&lt;p&gt;Consumer-driven contract testing with Pact uses different terms and concepts. If some terms in this short glossary may appear confusing at first, they will become clear later.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Consumer:&lt;/strong&gt; A service/component calling another service e.g. via a HTTP/REST API call, independent of the data flow direction (it does not matter if the HTTP request is a GET, PUT, POST, PATCH or DELETE).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provider:&lt;/strong&gt; A service/component being called from another service e.g. via a HTTP/REST interface. It may have more than one HTTP endpoint. It is semantically the same as the aforementioned producer. &lt;strong&gt;&lt;em&gt;From this point on, we will use the term provider instead of producer.&lt;/em&gt;&lt;/strong&gt; One producer can have more than one provider.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mock Service Provider:&lt;/strong&gt; Used by tests in the consumer pipeline to mock the actual provider. Integration-like tests can be run without the actual provider.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interaction:&lt;/strong&gt; A request and response pair, e.g. a concrete GET request with its parameters and the response data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contract (or Pact file):&lt;/strong&gt; A contract consists of a collection of interactions. Actually it is a JSON text file containing serialized interactions. The file is generated by running the consumer-side pact test. In addition it contains the consumer name, provider name, metadata with the pact specification version and the pact verfication.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pact verfication:&lt;/strong&gt; A Pact file is verified by replaying the requests against the (real) provider, the responses must match those in the Pact file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provider state:&lt;/strong&gt; Describes the state that the provider should be in when a given request is replayed and usually has a “&lt;a href="https://stackoverflow.com/questions/12071344/what-are-fixtures-in-programming" rel="noopener noreferrer"&gt;fixture&lt;/a&gt; name” such as “when user Joe Doe exists”.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pact specification:&lt;/strong&gt; It is a &lt;a href="https://github.com/pact-foundation/pact-specification" rel="noopener noreferrer"&gt;document&lt;/a&gt; describing the structure of the generated Pact file, allowing for interoperability between different languages/Pact implementations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pact broker:&lt;/strong&gt; The Pact Broker is a central application for sharing consumer driven contracts and verification results. It is optimised for use with Pact.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Workflow and tests
&lt;/h3&gt;

&lt;p&gt;Before going into details, we first provide a 10000 feet view of the contract test workflow. A contract includes example requests and responses that serve as input for a mock provider (for tests on the consumer side) and a mock consumer (for tests on the provider side) against which the interface partners can be tested independently. Instead of testing the interface with an end-to-end test that requires both the real provider and consumer, two tests are performed on each side of the interface without direct dependency to the other side:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Feon-com%2Ftoyapp-pact-demo%2Fmaster%2Fimages%2FFlows.png%3Fversion%3D1581535215" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Feon-com%2Ftoyapp-pact-demo%2Fmaster%2Fimages%2FFlows.png%3Fversion%3D1581535215" alt="Image displaying the Pact workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Comsumer test
&lt;/h3&gt;

&lt;p&gt;This is all about consumer-driven contract testing, so let's examine the consumer test first. Before executing the actual consumer test, the initial step is to specify all interactions (we remember: collections of expected requests and responses) that are later included in the Pact file. While it is possible to manually create and modify Pact files with any editor of your choice, we highly encourage you to create/modify them automatically based on whatever DSL provided by your Pact framework. This is usually done inside the consumer test. The other task of the consumer test is to execute tests against the Pact mock provider with which the interactions of the Pact file are registered. This is done by real requests fired against the mock provider. The mock provider itself is also generated by the Pact framework. Then the consumer has to successfully process the responses provided by the mock provider, i.e. the responses defined in the contract. After successfully testing the consumer the generated Pact file is uploaded to a central place, e.g. to Pact broker &lt;sup&gt;4&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;We will later see in the hands-on chapter how to define interactions and write consumer tests with the Pact framework extension for JUnit 5.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Feon-com%2Ftoyapp-pact-demo%2Fmaster%2Fimages%2FConsumer_Flow.png%3Fversion%3D1581535215" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Feon-com%2Ftoyapp-pact-demo%2Fmaster%2Fimages%2FConsumer_Flow.png%3Fversion%3D1581535215" alt="Image displaying the Pact workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Provider test
&lt;/h3&gt;

&lt;p&gt;Provider tests serve for the provider verification where each request of the contract file is sent to the (real) provider, and the actual response generated is compared with the minimal expected response described in the contract. It is deliberatly called “minimal expected response” as there may not only be different consumers for different endpoints but also different consumers for one endpoint with different requirements about the response of this one endpoint. So it is sufficient for the verification that the subset required by this particular consumer is contained in the response &lt;sup&gt;5&lt;/sup&gt;. The verification passes if each request fulfills this requirement. In many cases the provider has to be in a particular state as defined in the glossary above. The Pact framework supports this by letting you set up the data described in the provider state before the interaction is replayed.&lt;/p&gt;

&lt;p&gt;If the provider wants to change its API by e.g. adding an additional attribute to the response, it can simply verify all existing contracts. If the verifications are successful, the contracts are not broken and so the changes should not break any of the consumers, too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Feon-com%2Ftoyapp-pact-demo%2Fmaster%2Fimages%2FProvider_Flow.png%3Fversion%3D1581535215" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Feon-com%2Ftoyapp-pact-demo%2Fmaster%2Fimages%2FProvider_Flow.png%3Fversion%3D1581535215" alt="Image displaying the Pact workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing Pact tests for the JVM with JUnit 5
&lt;/h2&gt;

&lt;p&gt;This is the hands-on part of this blog post. The toy application provided alongside this blog post was originally a POC for the Ktor framework &lt;sup&gt;6&lt;/sup&gt;. So the programming language used for Pact testing in this example is Kotlin. Apart from Docker it requires Java 11 so make sure to point your JAVA_HOME environment variable to the right directory. You can get the toy application from &lt;a href="https://github.com/eon-com/toyapp-pact-demo" rel="noopener noreferrer"&gt;here&lt;/a&gt;. After the download please run &lt;code&gt;./build.sh&lt;/code&gt; (using Terminal on macOS, Linux or &lt;a href="https://gitforwindows.org/" rel="noopener noreferrer"&gt;Git BASH&lt;/a&gt; on Windows) in order to see if everything works as expected. Please make sure that port 8080 on your local machine is available.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project structure
&lt;/h3&gt;

&lt;p&gt;You will find the following project structure: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;common: some cross cutting code shared between the services&lt;/li&gt;
&lt;li&gt;core-data-service: a service with core customer data used by other services&lt;/li&gt;
&lt;li&gt;customer-service: uses a subset from data provided by the core-data-service&lt;/li&gt;
&lt;li&gt;creditcheck: uses a different subset from data provided by the core-data-service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The data provided by the core-data-service will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;555&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"first_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Arnold"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"last_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Schwarzenegger"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"date_of_birth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1947-07-30"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"street"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"P.O. Box 1234"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"number"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"--"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"zip_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CA 90406"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"place"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Santa Monica"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"US"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;666&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"first_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bruce"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"last_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Willis"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"date_of_birth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1955-03-19"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;777&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"first_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sylvester"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"last_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Stalone"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"date_of_birth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1946-07-06"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Prerequisites for Maven
&lt;/h3&gt;

&lt;p&gt;As we decided to use Maven for our toy application we have to do a few things first. First of all we use the latest and greatest &lt;strong&gt;failsafe&lt;/strong&gt; and &lt;strong&gt;surefire&lt;/strong&gt; plugin version, in our case &lt;strong&gt;3.0.0-M4&lt;/strong&gt;. It supports both JUnit 5 and the Pact version we use. As opposed to a real world microservice scenario we have the luxury to run a multimodule Maven project. That is why we suggest to put the following snippet in our parent POM file inside the properties- and pluginManagement-section to avoid having this boilerplate in each and every module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;project&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;properties&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- [...] --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;failsafe.version&amp;gt;&lt;/span&gt;3.0.0-M4&lt;span class="nt"&gt;&amp;lt;/failsafe.version&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;surefire.version&amp;gt;&lt;/span&gt;3.0.0-M4&lt;span class="nt"&gt;&amp;lt;/surefire.version&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- [...] --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;pact.dir&amp;gt;&lt;/span&gt;target/pacts&lt;span class="nt"&gt;&amp;lt;/pact.dir&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;pact.broker.schema&amp;gt;&lt;/span&gt;http&lt;span class="nt"&gt;&amp;lt;/pact.broker.schema&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;pact.broker.host&amp;gt;&lt;/span&gt;localhost&lt;span class="nt"&gt;&amp;lt;/pact.broker.host&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;pact.broker.port&amp;gt;&lt;/span&gt;8080&lt;span class="nt"&gt;&amp;lt;/pact.broker.port&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/properties&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- [...] --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;build&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- [...] --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;pluginManagement&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;plugins&amp;gt;&lt;/span&gt;
                &lt;span class="c"&gt;&amp;lt;!-- [...] --&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;maven-surefire-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;${surefire.version}&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.junit.jupiter&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;junit-jupiter-engine&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;${junit.version}&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/dependencies&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;systemPropertyVariables&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;pact.rootDir&amp;gt;&lt;/span&gt;${pact.dir}&lt;span class="nt"&gt;&amp;lt;/pact.rootDir&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;pact.verifier.publishResults&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/pact.verifier.publishResults&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;/systemPropertyVariables&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;maven-failsafe-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;${failsafe.version}&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/plugins&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;au.com.dius&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;pact-jvm-provider-maven&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;4.0.0-beta.5&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;serviceProviders/&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;pactDirectory&amp;gt;&lt;/span&gt;${pact.dir}&lt;span class="nt"&gt;&amp;lt;/pactDirectory&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;pactBrokerUrl&amp;gt;&lt;/span&gt;${pact.broker.schema}://${pact.broker.host}:${pact.broker.port}&lt;span class="nt"&gt;&amp;lt;/pactBrokerUrl&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;tags&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;tag&amp;gt;&lt;/span&gt;master&lt;span class="nt"&gt;&amp;lt;/tag&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/tags&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/pluginManageement&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/build&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/project&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please keep in mind this is an example application only. It's perfeclty up to you how to inject your properties based on the currently used enviroment.&lt;/p&gt;

&lt;p&gt;A closer look at the configuration for &lt;strong&gt;pact-jvm-provider-maven&lt;/strong&gt; reveals there is also the optional possibility to define tags. Dealing with tags in a detailed manner would go beyond the scope of this blog post; hence we discuss it just briefly: if both consumer and provider use the same tag it will facilitate implementing your user stories as the provider verification test just registers with an adequately tagged contract. This can be achievedy by dynamically inserting tag names e.g. by using the current Git branch name (in our simplified example we always use &lt;strong&gt;master&lt;/strong&gt;). Hint: As there is a certain possibility that no appropriate tag is propagated to the Pact broker accidently you should always use some kind of fallback tag (e.g. &lt;strong&gt;master&lt;/strong&gt; or &lt;strong&gt;latest&lt;/strong&gt;) for the provider as otherwise your provider verification test might spuriously pass.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;                    &lt;span class="nt"&gt;&amp;lt;tags&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;tag&amp;gt;&lt;/span&gt;master&lt;span class="nt"&gt;&amp;lt;/tag&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;tag&amp;gt;&lt;/span&gt;${git.branch}&lt;span class="nt"&gt;&amp;lt;/tag&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/tags&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Writing the Spec
&lt;/h3&gt;

&lt;p&gt;As Pact is consumer-driven, the spec that will define the contract is a test written on the consumer side.&lt;/p&gt;

&lt;p&gt;First of all we have to mark our test class with the &lt;strong&gt;@ExtendWith&lt;/strong&gt; annotation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@ExtendWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PactConsumerTestExt&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomerServicePactTest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// [...]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the test class you will find the actual method which will create the Pact file upon execution (abridged and refactored with removed constants for better readibility in this blog post):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="nd"&gt;@Pact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"core-data-service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"customer-service"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;createPact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;PactDslWithProvider&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;RequestResponsePact&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;given&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"all test customers are available"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// this title will later be the state name&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uponReceiving&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"get request on /v1/customers"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// internal descriptor&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/v1/customers"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// the actual path&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// HTTP method&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;willRespondWith&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// expected HTTP status code &lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PactDslJsonBody&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;integerType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"page"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;minArrayLike&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"payload"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;integerType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;555&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringMatcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"first_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;".+"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Any"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringMatcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"last_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;".+"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Any"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;closeObject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;closeArray&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;given&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Arnold Schwarzenegger is available"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uponReceiving&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"get request on /v1/customers/555"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/$version/$segment/555"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;willRespondWith&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PactDslJsonBody&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;integerType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;555&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"first_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Arnold"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"last_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Schwarzenegger"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;// for exact matches you can also use a JSON string directly&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toPact&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's examine our first interaction described with “all test customers are available”: Upon receiving an HTTP GET request at the path &lt;strong&gt;/v1/customers&lt;/strong&gt; we assume a response with status code 200 and a response body which is described using the &lt;a href="https://github.com/DiUS/pact-jvm/tree/master/consumer/pact-jvm-consumer-java8" rel="noopener noreferrer"&gt;Lambda DSL for Pact&lt;/a&gt;. In contrast to the second interaction we are not interested in exact matches so we use stringMatcher instead of stringType here, resulting in using regular expressions instead of strings.&lt;/p&gt;

&lt;p&gt;After executing the build script mentioned above, these interactions will be part of the pact contract file&lt;br&gt;
&lt;strong&gt;customer-service/target/pacts/customer-service-core-data-service.json&lt;/strong&gt;. There will also be a second pact contract file for the interactions of the provider with the creditcheck service: &lt;strong&gt;creditcheck/target/pacts/creditcheck-core-data-service.json&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Testing against the Mock Server
&lt;/h3&gt;

&lt;p&gt;After having defined our interactions we also have to test them against the mock server. This is done in the same file by executing the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="nd"&gt;@PactTestFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pactMethod&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"createPact"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@Throws&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mockServer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;MockServer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;allCustomersResponse&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mockServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUrl&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"/$version/$segment"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;returnResponse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;assertThat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;allCustomersResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;statusLine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;isEqualTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;singleCustomerResponse&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mockServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUrl&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"/$version/$segment/555"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;returnResponse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;assertThat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;singleCustomerResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;statusLine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;isEqualTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each URL segment has to be called exaclty one time, otherwise the test will break. Of course you can also test the HTTP response body.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pact verfication
&lt;/h3&gt;

&lt;p&gt;Now we change to the provider side and prepare the states necessary to run the pact tests there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@ExtendWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ApplicationContextExtension&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;PersistenceExtension&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Provider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"core-data-service"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@PactBroker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scheme&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pactBrokerScheme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pactBrokerHost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pactBrokerPort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CoreDataServicePactVerificationTest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;companion&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;PROVIDER_URL&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http://localhost:${port}"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@BeforeEach&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;PactVerificationContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpTestTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PROVIDER_URL&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@TestTemplate&lt;/span&gt;
    &lt;span class="nd"&gt;@ExtendWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PactVerificationInvocationContextProvider&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;pactVerificationTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;PactVerificationContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verifyInteraction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"all test customers are available"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;allCustomersAvailable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;customers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;JSONResourceLoader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadCollectionFromResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/fixtures/data/all.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Customer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;runBlocking&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;Persistence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeCustomers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Arnold Schwarzenegger is available"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;selectedCustomerAvailable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;customer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;JSONResourceLoader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadFromResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/fixtures/data/555.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Customer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;runBlocking&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;Persistence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"there is no customer with id 0"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;noCustomerWithId0&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Nothing to do here&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"there is no customer with invalid id a"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;noCustomerForInvalidId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Nothing to do here&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this setup we use two custom extensions for JUnit 5 for application context (starting Ktor) and persistence (database setup and cleaning). The most important section is the method annotated with @BeforeEach where you set the test target (the object that defines the target of the test, which should point to your provider) on the PactVerificationContext. There are some other targets such as HttpsTestTarget and SpringBootHttpTarget, depending on what you need. You can see that the state is provided by inserting required customer data to the database. For more information on that see the &lt;strong&gt;common questions&lt;/strong&gt; section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running the complete Pact flow
&lt;/h3&gt;

&lt;p&gt;There is a script to be used to execute the complete flow in a simple manner. Once again, you will need Java 11 so make sure to point your JAVA_HOME environment variable to the right directory and then execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./run-pact-flow.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is the script in detail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="c"&gt;# restart docker compose for Pact broker at port 8080, see docker-compose.yml&lt;/span&gt;
docker-compose down
docker-compose &lt;span class="nb"&gt;rm
&lt;/span&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;span class="c"&gt;# install parent POM&lt;/span&gt;
mvn &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-N&lt;/span&gt;
&lt;span class="c"&gt;# install common jar&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ./common &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;exec &lt;/span&gt;mvn clean &lt;span class="nb"&gt;install&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;# test and publish customer service Pact&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ./customer-service &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;exec &lt;/span&gt;mvn clean &lt;span class="nb"&gt;test &lt;/span&gt;pact:publish&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;# test and publich creditcheck Pact&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ./creditcheck &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;exec &lt;/span&gt;mvn clean &lt;span class="nb"&gt;test &lt;/span&gt;pact:publish&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;# verify Pact against real service&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ./core-data-service &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;exec &lt;/span&gt;mvn clean &lt;span class="nb"&gt;test &lt;/span&gt;pact:verify&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script shows the actual flow: first of all, a broker will be started on localhost:8080. After installing the common JAR dependency both consumers, &lt;strong&gt;customer-service&lt;/strong&gt; and &lt;strong&gt;creditcheck&lt;/strong&gt;, will be tested and their contracts will be published to the Pact proker. Finally the &lt;strong&gt;core-data-service&lt;/strong&gt; is verified against the contracts uploaded to the broker.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pact broker entry page
&lt;/h4&gt;

&lt;p&gt;Just go to &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt; after having executed the script. You will find the entry page with an overview displaying several columns: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Feon-com%2Ftoyapp-pact-demo%2Fmaster%2Fimages%2FScreen_1.png%3Fversion%3D1581535215" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Feon-com%2Ftoyapp-pact-demo%2Fmaster%2Fimages%2FScreen_1.png%3Fversion%3D1581535215" alt="Image displaying the Pact broker's entry page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Pact broker relationships
&lt;/h4&gt;

&lt;p&gt;If you further click on &lt;strong&gt;core-data-service&lt;/strong&gt; you will find all relationsships between provider and consumers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Feon-com%2Ftoyapp-pact-demo%2Fmaster%2Fimages%2FScreen_2.png%3Fversion%3D1581535215" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Feon-com%2Ftoyapp-pact-demo%2Fmaster%2Fimages%2FScreen_2.png%3Fversion%3D1581535215" alt="Image displaying the Pact broker's relationships"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Pact broker contract (excerpt)
&lt;/h4&gt;

&lt;p&gt;Another click on the line/edge between &lt;strong&gt;customer-service&lt;/strong&gt; and &lt;strong&gt;core-data-service&lt;/strong&gt; will take you to this page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Feon-com%2Ftoyapp-pact-demo%2Fmaster%2Fimages%2FScreen_3.png%3Fversion%3D1581535215" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Feon-com%2Ftoyapp-pact-demo%2Fmaster%2Fimages%2FScreen_3.png%3Fversion%3D1581535215" alt="Image displaying the Pact broker's contract"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here you can find the actual contract displaying all related information. Make yourself familiar with the &lt;a href="https://github.com/pact-foundation/pact_broker" rel="noopener noreferrer"&gt;Pact broker&lt;/a&gt; as it is an easy (if not the easiest) way of exchanging Pact contracts and visualising them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common questions
&lt;/h2&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What about API-first as design approach?
&lt;/h3&gt;

&lt;p&gt;API-first/API-led/API-driven mean that the design of the API stands at the beginning of a project. The very first step should be to think about how the API will look and work in detail so that it is as universal as possible, extensible and easy to understand. Without the API-first approach, on the other hand, there is a great risk that the API will be heavily geared towards the implementation and use cases of existing systems, bearing the risk that the API is not universal or extensible enough for future systems. For REST-based APIs there are tools such as &lt;a href="https://swagger.io/" rel="noopener noreferrer"&gt;OpenAPI Specification/Swagger&lt;/a&gt;, &lt;a href="https://raml.org/" rel="noopener noreferrer"&gt;RAML&lt;/a&gt;, &lt;a href="https://apiblueprint.org/" rel="noopener noreferrer"&gt;API Blueprint&lt;/a&gt;, &lt;a href="https://apidocjs.com/" rel="noopener noreferrer"&gt;apiDoc&lt;/a&gt; and &lt;a href="https://github.com/slatedocs/slate" rel="noopener noreferrer"&gt;slate&lt;/a&gt; that support an API-first approach &lt;sup&gt;7&lt;/sup&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does Pact replace OpenAPI Specification aka Swagger?
&lt;/h3&gt;

&lt;p&gt;No. &lt;a href="https://swagger.io/" rel="noopener noreferrer"&gt;Swagger&lt;/a&gt; is a framework that allows complete description of the structure of your APIs. You can also automatically built client libraries or server stubs based on Swagger documentation, and vice versa, create Swagger specs based on annotations used in your source code. As opposed to this, Pact contracts describe what a particular consumer expects from the API request response. Of course this has also some charachteristics of a documentation, however, a provider can have more than one consumer, and thus more than one contract, so Swagger is a centralized overview over all parameters, return values and authorization information whereas Pact focusses on service-to-service interactions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is Pact suitable for public APIs?
&lt;/h3&gt;

&lt;p&gt;Pact is an appropriate solution when both consumer(s) and provider can establish some sort of collaboration or discussion. Of course this is not feasible for public APIs with dozends or even hundrets of different client stacks. In case you merely want to make sure that your public API and your implementation do not diverge, &lt;a href="https://github.com/codecentric/hikaku" rel="noopener noreferrer"&gt;Hikaku&lt;/a&gt; combined with &lt;a href="https://swagger.io/" rel="noopener noreferrer"&gt;Swagger&lt;/a&gt;  (or &lt;a href="https://raml.org/" rel="noopener noreferrer"&gt;RAML&lt;/a&gt;) might be a good choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does Pact only support synchronous HTTP/REST-based communication?
&lt;/h3&gt;

&lt;p&gt;No, it is not restricted to HTTP/REST. Pact version 3.0 introduces messages for &lt;a href="https://github.com/Pact-foundation/Pact-specification/tree/version-3#version-30" rel="noopener noreferrer"&gt;services that communicate via event streams and message queues&lt;/a&gt;. There is also a blogpost by the makers of Pact, describing &lt;a href="https://medium.com/@DoorDash/contract-testing-with-Pact-7cf108ced8c4" rel="noopener noreferrer"&gt;Contract Testing Serverless and Asynchronous Applications&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How can I deal with optional attributes/fields?
&lt;/h3&gt;

&lt;p&gt;The concept for optional attributes is not provided by Pact. If you want to explicitly test them just provide two interactions with different state, one with the consumer's absolute minimum of response attributes and one with all possible attributes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does consumer-driven mean "consumer-dictated"?
&lt;/h3&gt;

&lt;p&gt;Not at all. It is vital to understand that Pact should be used to encourage API-led design, increase confidence, and facilitate inter-team discussions, not replace them! &lt;/p&gt;

&lt;h3&gt;
  
  
  Can the Pact verification include a database setup?
&lt;/h3&gt;

&lt;p&gt;According to the most sources including official documentation it even should: &lt;a href="https://docs.pact.io/implementation_guides/ruby/provider_states#global-state" rel="noopener noreferrer"&gt;Global state&lt;/a&gt;, &lt;a href="https://techblog.poppulo.com/pacts-provider-states-and-matchers/" rel="noopener noreferrer"&gt;Pact tests: what about state data?&lt;/a&gt;. Pact tests help avoid the hassle of setting up complete environments for end-to-end or full-fledged integration test talking to other systems. A database is part of the realm of your microservice and thus no "other system" from a business point of view (there should be no databases shared by two ore more microservices) and setting up test databases using &lt;a href="https://www.testcontainers.org/modules/databases/" rel="noopener noreferrer"&gt;database containers&lt;/a&gt; is an easy task.&lt;/p&gt;

&lt;p&gt;However, no best practice and no good idea should be turned into a dogma: if you have enough integration tests including (real) database setup, it is perfectly okay to mock database connections or use in-memory replacements for your Pact tests in order to reduce build times.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary and final thoughts
&lt;/h2&gt;

&lt;p&gt;This blog post shows how to utilize Pact to test distributed service interactions without adding the complexitiy of with full-blown end-to-end tests. We have also learned about basic concepts such as the test pyramid and a concrete Pact implementation. Pact facilitates team discussions and is not designed to replace them. Moreover, it fosters API first design and increases your confidence when deploying APIs that have been evolved over time. Pact is neither recommended for public APIs nor for being used as a comprehensive API documentation. However, interactions between services can be well documented with Pact. As Pact supports different programming languages you can use Pact even if your services are written in different languages.&lt;/p&gt;




&lt;p&gt;[1] A good explanation for the difference between test doubles can be found under &lt;a href="https://blog.pragmatists.com/test-doubles-fakes-mocks-and-stubs-1a7491dfa3da" rel="noopener noreferrer"&gt;Test Doubles — Fakes, Mocks and Stubs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;[2] Unit-, integration-, end-to-end etc. test are a classification concerning scope and granularity, they are technology facing. In contrast to that the term "acceptance test" is business facing, it describes the fact, that the test gives relevant business centered feedback about the specified functionality. Acceptance tests can be set on on different levels of granularity, but in everyday speech they are most often related to tests in the upper part of the test pyramid.&lt;/p&gt;

&lt;p&gt;[3] Mocking the producer can be an arduous work itself, too. The system to be mocked might be complex and (manual) mocking often leads to overly specified tests and fixtures.&lt;/p&gt;

&lt;p&gt;[4] Part of a full consumer workflow is a mechanism preventing deployment of the consumer consumer as long as the provider tests are not successful. If you use a Pact broker, you will find a webhook mechanism which can be used to trigger consumer builds after successful execution of the provider test.&lt;/p&gt;

&lt;p&gt;[5] In the latter case each client has to be configured in a way that it ignores additional attributes inside the response (according to &lt;a href="https://devopedia.org/postel-s-law" rel="noopener noreferrer"&gt;Postel's law&lt;/a&gt;). When using Jackson as JSON processor/(de-)serializer, this can be done with something like &lt;code&gt;ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)&lt;/code&gt;, ideally at a central location of your code.&lt;/p&gt;

&lt;p&gt;[6] The toy application includes the following technologies: &lt;a href="https://kotlinlang.org/" rel="noopener noreferrer"&gt;Kotlin&lt;/a&gt;, &lt;a href="https://ktor.io/" rel="noopener noreferrer"&gt;Ktor&lt;/a&gt; (microframework for Kotlin), &lt;a href="https://github.com/JetBrains/Exposed" rel="noopener noreferrer"&gt;Exposed&lt;/a&gt; (lightweight SQL library written for Kotlin), &lt;a href="https://junit.org/junit5/" rel="noopener noreferrer"&gt;JUnit 5&lt;/a&gt;, and good old &lt;a href="https://maven.apache.org/" rel="noopener noreferrer"&gt;Maven&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;[7] Using Swagger is not a wrong choice as it is feature-rich and you can choose between two different approaches, &lt;strong&gt;contract-first&lt;/strong&gt; and &lt;strong&gt;code-first&lt;/strong&gt;. For contract first your APIs are designed using an editor. With &lt;a href="https://github.com/swagger-api/swagger-codegen" rel="noopener noreferrer"&gt;Swagger Codegen&lt;/a&gt; both client and server code can be generated directly from it and there are generators for all common languages. In code-first development, the specification takes its starting point in the program code (e.g. JAVA interfaces/REST endpoints). Swagger annotations make it possible to set the corresponding OpenAPI specification properties in Java. Sometimes the term contract-first is used synonymously with API-first.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
