{"id":16321169,"url":"https://github.com/christian-draeger/pact-example","last_synced_at":"2025-03-21T11:31:27.651Z","repository":{"id":45989071,"uuid":"148831010","full_name":"christian-draeger/pact-example","owner":"christian-draeger","description":"Example project to demonstrate Contract Testing via Pact.","archived":false,"fork":false,"pushed_at":"2023-02-16T07:41:34.000Z","size":1298,"stargazers_count":64,"open_issues_count":0,"forks_count":29,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-01T05:41:24.701Z","etag":null,"topics":["consumer-driven-contracts","contract-testing","docker-compose","java","kafka","kotlin","maven","messaging","pact","pact-broker","pact-demo","pact-jvm","pact-node","pact-tests","react","reactjs","spring-boot","spring-boot-cli","spring-cloud-contract","tutorial"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/christian-draeger.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["christian-draeger"],"custom":["https://www.paypal.me/skrapeit"]}},"created_at":"2018-09-14T19:06:43.000Z","updated_at":"2025-01-07T08:09:42.000Z","dependencies_parsed_at":"2024-10-29T07:45:30.783Z","dependency_job_id":null,"html_url":"https://github.com/christian-draeger/pact-example","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christian-draeger%2Fpact-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christian-draeger%2Fpact-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christian-draeger%2Fpact-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christian-draeger%2Fpact-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/christian-draeger","download_url":"https://codeload.github.com/christian-draeger/pact-example/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244135898,"owners_count":20403797,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["consumer-driven-contracts","contract-testing","docker-compose","java","kafka","kotlin","maven","messaging","pact","pact-broker","pact-demo","pact-jvm","pact-node","pact-tests","react","reactjs","spring-boot","spring-boot-cli","spring-cloud-contract","tutorial"],"created_at":"2024-10-10T22:46:48.494Z","updated_at":"2025-03-21T11:31:27.267Z","avatar_url":"https://github.com/christian-draeger.png","language":"Kotlin","funding_links":["https://github.com/sponsors/christian-draeger","https://www.paypal.me/skrapeit"],"categories":[],"sub_categories":[],"readme":"![contract](documentation/contract.jpg)\n\n# Pact Example [![Build Status](https://travis-ci.org/christian-draeger/pact-example.svg?branch=master)](https://travis-ci.org/christian-draeger/pact-example)\n\nThis is an example project to give an overview about **Consumer Driven Contract Testing**.\n\n## Table of Contents\n* [Prolog](#prolog)\n\t* [Effective test suites with short feedback loop](#effective-test-suites-with-short-feedback-loop)\n\t* [The problem with E2E integration testing](#the-problem-with-e2e-integration-testing)\n* [Intro to Consumer Driven Contract Testing](#intro-to-consumer-driven-contract-testing)\n* [What?](#what)\n* [Intro to Pact](#intro-to-pact)\n\t* [The Motivation](#the-motivation-of-this-example-implementations)\n\t* [REST](#rest-example-server-to-server-communication)\n\t\t* [Consumer](#the-consuming-application)\n\t\t\t* [Defining a Pact](#defining-a-pact)\n\t\t\t\t* [Define](#define)\n\t\t\t\t* [Test](#test)\n\t\t\t\t* [Publish](#publish)\n\t\t\t\t\t* [Pact Broker intro](#the-broker)\n\t\t\t\t\t* [Broker Setup with docker-compose](#broker-setup-with-docker-compose)\n\t\t\t\t\t* [Upload contract to broker](#upload-contract-to-broker)\n\t\t\t* [Best Practices](#best-practices-(on-consumer-side))\n\t\t* [Producer / Provider](#the-providing-application)\n\t\t\t* [Verify a Pact](#verify-a-pact)\n\t\t\t\t* [Test](#verification-test)\n\t\t\t* [Best Practices](#best-practices-(on-producers-side))\n\t* [Javascript Consumer](#javascript-consumer)\n\t\t* [Define](#define-1)\n\t\t* [Test](#test-1)\n\t\t* [Publish](#publish-1)\n\t* [Spring Cloud Contract meets Pact](#spring-cloud-contract-meets-pact)\n\t* [Messaging](#messaging-example)\n\t* [Extra infos on Pact](#extra-infos-on-pact)\n* [Helpful links](#helpful-links)\n\n## Prolog\n\n\u003e When setting up a continuous deployment pipeline for any project, having a purposeful testing plan is of utmost importance.\n\n### Effective test suites with short feedback loop\n\nAn _effective_ test suite includes a combination of _testing strategies_ that leads to high test coverage, \nthat in turn drives _confidence_. \nThese strategies are typically in the form of unit, component, integration and acceptance tests. \nMonitoring and alerting too.\n\nThe test suite needs to run wicked **_fast_**, and be **_reliable_**. \nThis cannot be stressed enough. If tests are flakey (i.e. often return false negatives or positives) \nit cannot be depended on to give us the desired confidence that we need.\n\nTests also need to run as early as possible in the continuous deployment pipeline to **_shorten the \nfeedback loop_** for the developer. So ideally, most tests should be designed to run when pull requests \nare built (on standalone build agents that are sandboxed from the application environment). \nTo achieve this requirement, tests must make no assumption about the availability of any of its \nexternal dependencies, and be designed to run in **_isolation_**.\n\nTests that are designed to be fast, reliable and isolate failure will have a short and \neffective feedback loop that informs the developer with confidence whether the product is working or not.\n\n### The problem with E2E integration testing\n\nUnit tests is a good example of one such testing process that achieves the desired effectiveness \nbeing aspired to — they are fast, reliable and isolate failure. \nHowever, unit tests on their own are not enough because they give no guarantee that the tested \nunits work well together.\n\nIn the absence of the perfect unit test suite, end-to-end (E2E) integration tests are typically \nthe testing strategy of choice that is used to try and ascertain confidence in the system working \nas a whole.\n\nEven though E2E tests are full of promise to assert the overall product working a whole \nfrom a user’s perspective, they [quickly become a very bad idea](https://blog.thecodewhisperer.com/permalink/integrated-tests-are-a-scam) \nbecause of their [awful feedback loop](https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html) — slow, unreliable and depend on too many things at once.\n\n### Intro to Consumer Driven Contract Testing\n\nAn alternative testing strategy that complements the deficiency of unit tests but verifies that \ncomponents with external dependencies work together is integration contract testing.\nThe [concept](https://www.martinfowler.com/articles/consumerDrivenContracts.html) isn’t new, \nbut with the mainstream acceptance of microservices, \nit's important to remind people that consumer-driven contracts are an essential \npart of a mature microservice testing portfolio, enabling independent \nservice deployments.\n\nWhen two independently developed services are collaborating, \nchanges to the supplier’s API can cause failures for all its consumers. \nConsuming services usually cannot test against live suppliers since such \ntests are slow and brittle, so it’s best to use Test Doubles (mocks), \nleading to the danger that the test doubles get out of sync with the real \nsupplier service. Consumer teams can protect themselves from these failures \nby using integration contract tests – tests that compare actual service \nresponses with test values. While such contract tests are valuable, \nthey are even more useful when consuming services provide these tests to \nthe supplier, who can then run all their consumers’ contract tests to determine \nif their changes are likely to cause problems.\n\nContract testing is immediately applicable anywhere where you have two \nservices that need to communicate - such as an API client and a web front-end\nor for instance to services communicating via messaging queues. \nAlthough a single client and a single service is a common use case, \ncontract testing really shines in an environment with many services \n(as common for a microservice architecture). \nHaving well-formed contract tests makes it easy for developers to avoid \nversion hell. Contract testing is the killer app for microservice development and deployment.\n\nIn general, a contract is between a consumer (for instance a client that wants \nto receive some data) and a provider (for instance an API on a server that \nprovides the data the client needs). In microservice architectures, \nthe traditional terms client and server are not always appropriate -- for example, \nwhen communication is achieved through message queues (we'll have a look at this as well).\n\n#### Benefits in short\n* enable services to be deployed independently\n* enables teams to work independently from each other\n* enables verification of external endpoints - am i building what is wanted?\n\n### Intro to Pact\n\n![pact logo](documentation/pact-logo.png)\n\n[Pact](https://docs.pact.io) is a consumer-driven contract testing tool. \nThis means the contract is written as part of the consumer tests. \nA major advantage of this pattern is that only parts of the communication \nthat are actually used by the consumer(s) get tested. \nThis in turn means that any provider behaviour not used by current consumers \nis free to change without breaking tests.\n\nPact enables consumer driven contract testing, \nproviding a mock service and DSL for the consumer project, \ninteraction playback and verification for the service provider project.\n\n![pact diagram](documentation/pact_two_parts.png)\n\nThe Pact family of testing frameworks \n(Pact-JVM, Pact Ruby, Pact .NET, Pact Go, Pact.js, Pact Swift etc.) \nprovide support for Consumer Driven Contract Testing between dependent systems \nwhere the integration is based on HTTP (or message queues for some of the implementations).\n\n\n### the motivation of this example implementations\nBecause [Pact](https://docs.pact.io/) is supporting so much languages and different ways of doing things and \nthey have a distributed documentation it can get messy and a bit annoying to search \nor better say filter for the information you particularly want / need.\nOnly for the JVM there are currently ~20 different extensions / dependencies (plugins not included). 🤯\n\n\u003e_**In my opinion it's absolutely awesome to get decent support for different languages and frameworks,\n\u003ebut it can become quite hard to keep track of all the already existing stuff (especially if you're a newbie to Pact).**_\n\nFor this reason I decided to write a compact step by step guide with working examples\nusing Maven as build tool and provide each a Kotlin and a Java example of the test implementation.\n(😏 and a Javascript Consumer implementation)\n\n## What? \n\nWhat's going on here (in short):\n* Test implementation examples: \n\t* Consumer: Kotlin, Java, Javascript\n\t* Producer: Kotlin and Java\n* Contract repository: [Pact Broker](#publish)\n\t* via docker-compose\n* Functional API tests: WireMock\n* Build-tool: Maven\n\nIncluded examples are: How to test services that are talking REST as well as examples\nregarding how to ensure your services that are communication via messaging providing data in the \ncorrect format (from the consumers point of view).   \n\nThe **REST-Example** includes two applications where one is acting as a producer \n(webservice with rest endpoint) and a consumer \n(a CLI app that prints data received from the producer to console if executed).\n\nBoth of the applications (producer and consumer) are testing there-self.\nThe Consumer-Apps dependencies (having the Producer-App available, \na working internet connection and getting a suitable response) can be detached by\nmocking (e.g. WireMock) to run locally and independent.\nGreat!!! so far so good.\nWe want go a step further and decouple the release cycles of our microservices.\n\n##### But how to make sure the Producers (supplier) response is in a Suitable format for the Consumer?\n\n🤝 In a good relationship we know what to expect from each other and so should our services do.\n\n#### Let's make a _Pact_\n\nWhat is a Pact? 🤷‍\n\n\u003e A formal agreement between individuals or parties.\nSynonyms: agreement, protocol, deal, contract \n\u003e\u003e~ Oxford Dictionaries​\n\nIn Terms of Contract Testing you should always proceed according to the following schema when implementing a Pact:\n\n* Start implementing on the Consumer side\n\t* define your contract\n\t* verify your contract against a mock\n\t* publish your contract\n* End up verifying the contract on Producer side\n\n\u003e **_A few words in advance:_** \n\u003e\u003e Don't get confused by the Consumer / Producer wording - it is not related to the data flow!\n\u003e\u003e Producer in the context of Pact describes who is providing the API.\n\u003e\u003e That means for instance if you make a POST-request to an API - the API providing application is the _Producer_, where the application that is doing the request is the _Consumer_ on the other hand.\n\n\nRegarding the example implementations we will focus on the **[HTTP based integration](#rest-example-server-to-server-communication) first** and _later on_ we having a look at [**messaging queues**](#messaging-example).\n\n# REST Example (Server to Server communication)\n\n![server-2-server-diagram](documentation/server-2-server.png)\n\n###### The Consuming Application\n## Defining a Pact\nDefining a Pact should be splitted into 3 steps:\n* [Define](#define)\n* [Test](#test)\n* [Publish](#publish)\n\n\u003e If you are looking for an example on how to define a contract by using Javascript go [here](#javascript-consumer).  \n\n### Define\nWe'll start defining our Pact at the **Consumer** Application. \nI mean hey, we want to work Consumer Driven and who could know its \nrequirements regarding a producer API better then the Consumer itself?\n\n#### prerequisites on consumer side\nFirst let's add the relevant **Pact** dependency for our use-case to the consumer applications *pom.xml*.\nI'm using the [pact-jvm-consumer-java8](https://github.com/DiUS/pact-jvm/tree/master/pact-jvm-consumer-java8) dependency here _(an extension for the pact DSL provided by [pact-jvm-consumer](https://github.com/DiUS/pact-jvm/blob/master/pact-jvm-consumer))_ because it\nprovides a nice lambda based DSL for use with Junit to build consumer tests.\n\n``` xml\n\u003cdependency\u003e\n\t\u003cgroupId\u003eau.com.dius\u003c/groupId\u003e\n\t\u003cartifactId\u003epact-jvm-consumer-java8_2.12\u003c/artifactId\u003e\n\t\u003cversion\u003e3.5.21\u003c/version\u003e\n\t\u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\nNow we are able to define how the **Producer** APIs response needs to look like from the **Consumers** point of view.\nWe'll begin by creating a test class named `ContractTest` that implements `ConsumerPactTestMk2`.\n\nYou'll need to implement `providerName()`, `consumerName()`, `createPact()` and `runTest()`.\n\nThe implementation of the `providerName()` method should return a string that describes the name of the provider API.\nSince our **Provider** is responsible for user data we should call it something like \"user-data-provider\":\n\n\u003e using kotlin\n\u003e``` kotlin\n\u003eoverride fun providerName(): String = \"user-data-provider\"\n\u003e```\n\n\u003e using java\n\u003e``` java\n\u003e@Override\n\u003eprotected String providerName() {\n\u003e\treturn \"user-data-provider\";\n\u003e}\n\u003e```\n\nThe implementation of the `consumerName()` method should return a string that describes the name of the consuming service.\nSince our **Consumer** is an cli-tool that displays user data we should call it something like \"user-data-cli\":\n\n\u003e using kotlin\n\u003e``` kotlin\n\u003eoverride fun consumerName(): String = \"user-data-cli\"\n\u003e```\n\n\u003e using java\n\u003e``` java\n\u003e@Override\n\u003eprotected String consumerName() {\n\u003e\treturn \"user-data-cli\";\n\u003e}\n\u003e```\n\n\u003e **Hint:** Don't test (worst-case scenario) all fields or HTTP status codes the Provider API supports with Pact. You don't want to break the Providers build on every change that's made over there (for instance if something changed that wouldn't influence the behavior on Consumer Apps side). Just be tide on the things the Consumer App really expects from the Provider API.\n\n\u003e **Take away:** To verify how your Producer Client behaves on scenarios like network errors or getting crappy data from the API you should use WireMock.\n\nNow let's define how a request from the **Consumer** looks like and what's the \nexpected format of the payload by implementing the `createPact()` method.\n\nWe are using the `PactDslWithProvider` builder to describe the request \nand (because we are expecting a response with a JSON body)\nthe `PactDslJsonBody` builder to define the payload:\n\n\u003e using kotlin:\n\u003e``` kotlin\n\u003eoverride fun createPact(builder: PactDslWithProvider): RequestResponsePact {\n\u003e\n\u003e\tval body = PactDslJsonBody()\n\u003e\t\t\t.stringType(\"firstName\")\n\u003e\t\t\t.stringType(\"lastName\")\n\u003e\t\t\t.numberType(\"age\")\n\u003e\t\t\t.`object`(\"ids\", PactDslJsonBody()\n\u003e\t\t\t\t\t.integerType(\"id\")\n\u003e\t\t\t\t\t.uuid(\"uuid\"))\n\u003e\n\u003e\treturn builder.uponReceiving(\"can get user data from user data provider\")\n\u003e\t\t\t.path(\"/user\")\n\u003e\t\t\t.willRespondWith()\n\u003e\t\t\t.status(200)\n\u003e\t\t\t.body(body)\n\u003e\t\t\t.toPact()\n\u003e}\n\u003e```\n\n\u003e using java:\n\u003e``` java\n\u003e@Override\n\u003eprotected RequestResponsePact createPact(PactDslWithProvider builder) {\n\u003e\tPactDslJsonBody body = new PactDslJsonBody()\n\u003e\t\t\t.stringType(\"firstName\")\n\u003e\t\t\t.stringType(\"lastName\")\n\u003e\t\t\t.numberType(\"age\")\n\u003e\t\t\t.object(\"ids\", new PactDslJsonBody()\n\u003e\t\t\t\t.integerType(\"id\")\n\u003e\t\t\t\t.uuid(\"uuid\")\n\u003e\t\t\t);\n\u003e\n\u003e\treturn builder.uponReceiving(\"can get user data from user data provider\")\n\u003e\t\t\t.path(\"/user\")\n\u003e\t\t\t.method(\"GET\")\n\u003e\t\t\t.willRespondWith()\n\u003e\t\t\t.status(200)\n\u003e\t\t\t.body(body)\n\u003e\t\t\t.toPact();\n\u003e}\n\u003e```\n\n### Test\nAt this point we should define our client-side test based on the defined request we\ndescribed in the step before. So let our *UserClient* (that is talking to the **Provider**)\ncall a mockServer (that is created for us by **Pact**) as we defined it in our `createPact()` implementation.  \n\n\u003eusing kotlin:\n\u003e``` kotlin\n\u003eoverride fun runTest(mockServer: MockServer) {\n\u003e   val expectedKeys = listOf(\"firstName\", \"lastName\", \"ids\", \"age\")\n\u003e   val result = UserClient(\"${mockServer.getUrl()}/user\").callProducer()\n\u003e   assertThat(result.keys).containsAll(expectedKeys)\n\u003e}\n\u003e```\n\n\u003eusing java:\n\u003e``` java\n\u003e@Override\n\u003eprotected void runTest(MockServer mockServer) {\n\u003e    List\u003cString\u003e expectedKeys = Arrays.asList(\"firstName\", \"lastName\", \"ids\", \"age\");\n\u003e    Map\u003cString, String\u003e result = new UserClient(mockServer.getUrl() + \"/user\").callProducer();\n\u003e    assertThat(result.keySet()).containsAll(expectedKeys);\n\u003e}\n\u003e```\n\n\u003e ##### So your test class should look something like [THIS](consumer/src/test/kotlin/com/example/demo/ContractTest.kt) if you are using Kotlin afterwards.\n\u003e ##### So your test class should look something like [THIS](consumer/src/test/kotlin/com/example/demo/JavaContractTest.java) if you are using Java afterwards.\n\nAt this point we already achieved a lot. We verified our *UserClient* is working correctly and\nwe created the contract definition - or better said, Pact generated one for us :) - our **Provider** will validate his Api against later on.\nYou can have a look at it under `/target/pacts/user-data-cli-user-data-provider.json` (it should look similar to [THIS](consumer/src/test/resources/example-pact.json) one).\n\n### Publish\n\n#### The Broker\nSharing is caring - In this Example we are using a broker to host our contracts. \nFor showcasing reasons we just start the [Pact-Broker](https://github.com/pact-foundation/pact_broker) and a postgres\ndatabase via docker-compose. In a real world scenario you probably want to run the broker permanently on a VM - so you should deploy it somewhere.\nBut because this example is focusing on Pact itself we'll proceed using docker to quickly get a running Pact broker.\n\nThe Pact Broker provides a repository for consumer driven contracts that:\n- tells you which versions of your applications can be deployed safely together\n- solves the problem of how to share pacts between consumer and provider projects\n- allows you to decouple your service release cycles\n- provides API documentation that is guaranteed to be up-to date\n- shows you real examples of how your services interact\n- allows you to visualise the relationships between your services\n- can integrate with other systems, such as Slack or your CI server, via webhooks\n\n#### Broker Setup with docker-compose\nTo archive a running Pact-Broker via docker-compose we put a file called `docker-compose.yml` in the root of our project.\n\n```yaml\nversion: '3'\n\nservices:\n\n  postgres:\n    image: postgres\n    healthcheck:\n      test: psql postgres --command \"select 1\" -U postgres\n    ports:\n      - \"5432:5432\"\n    environment:\n      POSTGRES_USER: postgres\n      POSTGRES_PASSWORD: password\n      POSTGRES_DB: postgres\n\n  broker_app:\n    image: dius/pact-broker\n    ports:\n      - \"80:80\"\n    links:\n      - postgres\n    environment:\n      PACT_BROKER_DATABASE_USERNAME: postgres\n      PACT_BROKER_DATABASE_PASSWORD: password\n      PACT_BROKER_DATABASE_HOST: postgres\n      PACT_BROKER_DATABASE_NAME: postgres\n      PACT_BROKER_LOG_LEVEL: DEBUG\n```\n\nAfterwards run: \n\n\t$ docker-compose up\n\t\n\u003e*Troubleshooting on Mac/Windows:* \n\u003eI get a \"initdb: could not create directory \"/var/lib/postgresql/data/pg_wal\": No space left on device\" error\n\u003e * Your docker VM has probably run out of disk space. \n\u003e \t* Try deleting some old images. (`docker rmi -f $(docker images -a -q)`)\n\u003e\t* check your docker config and increase its disk image size\n\nThereby we achieved to have a Pact-Broker running (on port 80). \nTo verify everything went well just open [http://localhost](http://localhost) in your browser.\nYou should see the Pact-Broker UI but no uploaded contract for now. \n\n#### Upload contract to broker\n\nTo upload the Contract add the following plugin to the consumers pom.xml\n\n```xml\n\u003cplugin\u003e\n\t\u003cgroupId\u003eau.com.dius\u003c/groupId\u003e\n\t\u003cartifactId\u003epact-jvm-provider-maven_2.12\u003c/artifactId\u003e\n\t\u003cversion\u003e3.5.11\u003c/version\u003e\n\t\u003cconfiguration\u003e\n\t\t\u003cpactBrokerUrl\u003ehttp://localhost:80\u003c/pactBrokerUrl\u003e\n\t\t\u003cprojectVersion\u003e${project.version}\u003c/projectVersion\u003e\n\t\t\u003ctrimSnapshot\u003etrue\u003c/trimSnapshot\u003e\n\t\u003c/configuration\u003e\n\u003c/plugin\u003e\n```\n\nAfterwards you are able to upload your contract to the broker by executing the following command:\n\n\t$ mvn verify pact:publish \n\t\nIf everything went well you should see your contract in the Pact-Broker UI.\n\n![pact uploaded](documentation/uploaded-but-not-verified.png)\n\nIn a real world project you should think about a suitable way to execute this command\nwithin your build chain - for instance everytime the Producer client implementation\nhas changed on the consumer side.\n\n### Best Practices (on Consumer side)\n* Use Pact for contract testing, not functional testing of the provider!!! (read more [here](https://docs.pact.io/best_practices/consumer#use-pact-for-contract-testing-not-functional-testing-of-the-provider) and [here](https://docs.pact.io/best_practices/consumer/contract_tests_not_functional_tests))\n* Use Pact for isolated (unit) tests ([read more...](https://docs.pact.io/best_practices/consumer#use-pact-for-isolated-unit-tests))\n* Think carefully about how you use it for non-isolated tests (functional, integration tests) ([read more...](https://docs.pact.io/best_practices/consumer#think-carefully-about-how-you-use-it-for-non-isolated-tests-functional-integration-tests))\n* Always make sure you made the latest pact available to the Provider!\n* Ensure all calls to the Provider go through classes that have been tested with Pact. ([read more...](https://docs.pact.io/best_practices/consumer#ensure-all-calls-to-the-provider-go-through-classes-that-have-been-tested-with-pact))\n\n# The Providing Application\n###### (the Producer)\n## Verify a Pact\n\nNow that we have a Contract defined by the Consumer our Provider have to verify it. \nOn the Provider side this test should always be executed in your build-chain to make sure you\nare not breaking things on Consumers side.\nIn contrast to the consumer tests, provider verification is entirely driven by the Pact framework (there's nothing better than things getting simple ❤️). \n\n### Verify\n#### prerequisites on Producer side\nIn our case, we want to start our _Spring-Boot_-based Producer app and \nhave the Pact being checked against it.\nThis is why we are going to use pact-jvm-provider-spring_2.12 package because\nit is bringing some really handy annotations into the game - you'll see what i mean in just a minute.\n\n```xml\n\u003cdependency\u003e\n\t\u003cgroupId\u003eau.com.dius\u003c/groupId\u003e\n\t\u003cartifactId\u003epact-jvm-provider-spring_2.12\u003c/artifactId\u003e\n\t\u003cversion\u003e3.5.23\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n\u003e if you're not using [Spring](http://spring.io) you should have a look here: [junit-provider](https://github.com/DiUS/pact-jvm/tree/master/pact-jvm-provider-junit)\n\n\u003e if you're not using [jUnit4](https://junit.org/junit4/) or [jUnit5](https://junit.org/junit5/) you should have a look here: [maven-provider](https://github.com/DiUS/pact-jvm/tree/master/pact-jvm-provider-maven)\n\n\u003e if you're using [gradle](https://gradle.org) instead of [maven](https://maven.apache.org) you should have a look here: [gradle-provider](https://github.com/DiUS/pact-jvm/tree/master/pact-jvm-provider-gradle)\n\n#### Verification Test\n\nThe second step of our contract verification is creating a test for the \nProducer using a mock client based on the contract.\nOur provider implementation will be driven by this contract in TDD fashion.\nThe Test implementation on the Producer side is pretty straight forward.\n\n\u003eusing kotlin:\n\u003e```kotlin\n\u003e@RunWith(SpringRestPactRunner::class)\n\u003e@Provider(\"user-data-provider\")\n\u003e@PactBroker(protocol = \"http\", host = \"localhost\", port = \"80\")\n\u003e@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)\n\u003e\n\u003eclass UserDataProviderContractIT {\n\u003e    @TestTarget\n\u003e    @JvmField\n\u003e    final val target: Target = SpringBootHttpTarget()\n\u003e}\n\u003e```\n\n\u003eusing java:\n\u003e```java\n\u003e@RunWith(SpringRestPactRunner.class)\n\u003e@Provider(\"user-data-provider\")\n\u003e@PactBroker(protocol = \"http\", host = \"localhost\", port = \"80\")\n\u003e@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)\n\u003epublic class JavaUserDataProviderContractIT {\n\u003e\n\u003e    @TestTarget\n\u003e    public final Target target = new SpringBootHttpTarget();\n\u003e}\n\u003e```\n\n\u003e ##### So your test class should look something like [THIS](producer/src/test/kotlin/com/example/demo/UserDataProviderContractIT.kt) if you are using Kotlin.\n\u003e ##### So your test class should look something like [THIS](producer/src/test/kotlin/com/example/demo/JavaUserDataProviderContractIT.java) if you are using Java.\n\nIn order to get the contract verification results replayed to the Pact-Broker \nit's necessary to set the property `pact.verifier.publishResults=true`.\nThis can rather be done by setting the property via the failsafe-plugin (which we use to run our integration tests) like so:\n```\n\u003cplugin\u003e\n\t\u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n\t\u003cartifactId\u003emaven-failsafe-plugin\u003c/artifactId\u003e\n\t\u003cconfiguration\u003e\n\t\t\u003csystemPropertyVariables\u003e\n\t\t\t\u003cpact.verifier.publishResults\u003etrue\u003c/pact.verifier.publishResults\u003e\n\t\t\t\u003cpact.provider.version\u003e${project.version}\u003c/pact.provider.version\u003e\n\t\t\u003c/systemPropertyVariables\u003e\n\t\u003c/configuration\u003e\n\u003c/plugin\u003e\n```\n\nOr by setting the property programmatically:\n```\nval props = System.getProperties()\nprops.put(\"pact.verifier.publishResults\", \"true\")\nSystem.setProperties(props)\n```\n\nIf you run your tests and set the system property you should see a verified contract in the Pact-Broker UI.\n\n![pact uploaded](documentation/uploaded-and-verified.png)\n\nA nice **Pact-Broker** feature in my opinion is the network graph that shows which services have dependencies to each other \nor let's better say which of them assure they there compatibility by having a Pact. 🤗 \n\n![broker-network-graph](documentation/broker-network-graph.png)\n\nWhen clicking on an arrow in the graph you'll see a detailed view describing the exact properties \na certain consumer relies on regarding the producers API.\nWhich is really great from Producers point of view to know it's consumers and furthermore what data they are consuming in detail.\n\n![broker-network-graph](documentation/broker-pact-details-consumer-cli.png)\n\n### Best Practices (on Producers side)\n* Ensure that the latest pact is being verified ([read more...](https://docs.pact.io/best_practices/provider#ensure-that-the-latest-pact-is-being-verified))\n* Ensure that Pact verify runs as part of your CI build\n\n# Javascript Consumer\n\nAs already mentioned Pact is supporting a bunch of languages. A very handy combination i saw in real world projects\nis defining a contract between a pure javascript based consumer (for instance a node.js app) doing ajax-requests\nagainst some backend server providing an API.\n\n![js-2-server-diagram](documentation/js-2-server.png)\n\nIn this example a basic [React](https://reactjs.org) app with [Jest](https://jestjs.io) as testing platform is assumed. \nYour project structure could look [as follows](https://github.com/christian-draeger/pact-example/tree/master/consumer-ui).\n\n#### Prerequisites\nFirst let's add the **pact** and **pact-node** dev dependency to the consumer applications *package.json*.\n\n\u003e The `pact-node` dependency is needed to publish your pact file to the broker. This could also be solved by\n\u003e using the pact maven or gradle plugin (depending on your build setup). But to keep the JS example a pure JS example\n\u003e i decided to go the pact-node way here.\n\n``` json\n\"devDependencies\": {\n    \"@pact-foundation/pact\": \"7.0.3\",\n    \"@pact-foundation/pact-node\": \"6.20.0\"\n}\n```\n\n### Define\nNow we are able to define how the **Producer** APIs response needs to look like from the **Consumers** point of view.\n\n#### Configure\nFirst of all we want Pact to to create a mock server for us, tell pact who is the consumer and the provider and where\nto place generated pact files.\n\n``` javascript 1.6\nimport { Pact } from \"@pact-foundation/pact\";\n\nconst pact = new Pact({\n\t\tconsumer: \"user-data-ui\",\n\t\tprovider: \"user-data-provider\",\n\t\tport: 4711,\n\t\tlog: path.resolve(process.cwd(), \"dist/logs\", \"pact.log\"),\n\t\tdir: path.resolve(process.cwd(), \"dist/pacts\"),\n\t\tlogLevel: \"WARN\",\n\t\tspec: 2, // \u003c-- it's important to use the same pact spec verion as the producer here\n\t\tcors: true\n\t});\n}\n```\n\n\u003e*Troubleshooting for Jest*\n\u003e I get a \"SecurityError: localStorage is not available for opaque origins\" error when executing tests \n\u003e * The root cause is often libraries looping over all jsdom properties and adding them to the global; \n\u003e\teven if you never use localStorage in your tests, some library or test framework you are depending on is \"using\" it in this manner.\n\u003e\tNote that this looping-and-copying technique is explicitly unsupported by jsdom.\n\u003e\t* [jest issue](https://github.com/facebook/jest/issues/6766)\n\u003e \t* [jsdom issue](https://github.com/jsdom/jsdom/issues/2304)\n\u003e\n\u003e To fix this you can set env config for non-browser environment by adding the following at the top of your test class: \n\u003e``` javascript 1.6\n\u003e/**\n\u003e * @jest-environment node\n\u003e */\n\u003e```\n\n\u003e **Hint:** Don't test (worst-case scenario) all fields or HTTP status codes the Provider API supports with Pact. You don't want to break the Providers build on every change that's made over there (for instance if something changed that wouldn't influence the behavior on Consumer Apps side). Just be tide on the things the Consumer App really expects from the Provider API.\n\n\u003e **Take away:** To verify how your Producer Client behaves on scenarios like network errors or getting crappy data from the API you should use WireMock.\n\n#### Configure Mock Server\n\nNow let's define how a request from the **Consumer** looks like and what's the \nexpected format of the payload.\n\n``` javascript 1.6\nimport { Matchers } from \"@pact-foundation/pact\";\n\nbeforeEach((done) =\u003e \n\tpact.setup()\n\t\t.then(() =\u003e {\n\t\t\t// define expected response\n\t\t\tconst expectedResponse = {\n\t\t\t\tfirstName: Matchers.like(\"aValidFirstName\"),\n\t\t\t\tlastName: Matchers.like(\"aValidLastName\"),\n\t\t\t\tage: Matchers.integer(100)\n\t\t\t};\n\t\n\t\t\t// define request\n\t\t\treturn pact.addInteraction({\n\t\t\t\tstate: \"some user available\",\n\t\n\t\t\t\tuponReceiving: \"a user request\",\n\t\n\t\t\t\twithRequest: {\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tpath: \"/user\",\n\t\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAccept: Matchers.term({\n\t\t\t\t\t\t\tmatcher: \"application/json\",\n\t\t\t\t\t\t\tgenerate: \"application/json\"\n\t\t\t\t\t\t})\n\t\t\t\t\t},\n\t\t\t\t},\n\t\n\t\t\t\twillRespondWith: {\n\t\t\t\t\tstatus: 200,\n\t\t\t\t\theaders: {\"Content-Type\": \"application/json;charset=UTF-8\"},\n\t\t\t\t\tbody: expectedResponse\n\t\t\t\t}\n\t\t\t});\n\t\t})\n\t\t.then(() =\u003e done())\n\t);\n\n```\n\n### Test\nAt this point we should define our client-side test based on the defined request we\ndescribed in the step before. So let our *UserClient* (that is talking to the **Provider**)\ncall the mockServer (that was created for us by **Pact**) as we defined it in our consumer test\nand validate our expected response. \n\n``` javascript 1.6\nit(\"can load user data\", () =\u003e {\n\n\texpect.assertions(3);\n\n\tconst url = `http://localhost:4711/user`;\n\n\tconst promise = fetchUserData(url);\n\n\treturn promise.then(response =\u003e {\n\t\texpect(response.status).toBe(200);\n\t\texpect(response.headers['content-type']).toBe(\"application/json;charset=UTF-8\");\n\t\texpect(response.data).toMatchObject({\n\t\t\tfirstName: \"aValidFirstName\",\n\t\t\tlastName: \"aValidLastName\",\n\t\t\tage: 100\n\t\t});\n\t});\n});\n```\n\n#### create pact file\nDon't forget to create the Pact file(s) after a successful test run.\n\n```\nafterAll(() =\u003e {\n\tpact.finalize();\n});\n```\n\n### Publish\n\nNow that we have successfully generated a Pact file (you'll find it in your build dir if everything went well)\nwe want to upload it to the Pact Broker. Generally should be solved via a build step that should be executed when your tests are running on your CI system,\nbut for demo purpose i'm going to upload it by calling `publishContract()` whenever the pact test succeeded.\n\n\n``` javascript 1.6\nimport { Publisher } from \"@pact-foundation/pact-node\";\n\nconst publishContract = () =\u003e {\n\n\tconst options = {\n\t\tpactFilesOrDirs: [path.resolve(process.cwd(), \"dist/pacts\")],\n\t\tpactBroker: \"http://localhost:80\",\n\t\tconsumerVersion: \"0.1.0\"\n\t};\n\n\tnew Publisher(options).publish();\n};\n```\n\n\u003e ##### So your test class should look something like [THIS](consumer-ui/src/userApiContract.pact.test.js)\n\nHaving a look at Pact-Broker UI you should see something like:\n![pact uploaded](documentation/ui-uploaded-but-not-verified.png)\n\n### make your Provider Test work\nWhen verifying a contract created by a Javascript consumer it is necessary to the following to your Producers Pact verification test.\n\n\u003eusing Kotlin:\n\u003e``` kotlin\n\u003e@State(\"some user available\")\n\u003efun userAvailable() {}\n\u003e```\n\n\u003eusing Java:\n\u003e``` java\n\u003e@State(\"some user available\")\n\u003epublic void userAvailable() {}\n\u003e```\n\n\u003e ##### So your test class should look something like [THIS](producer/src/test/kotlin/com/example/demo/UserDataProviderContractIT.kt) if you are using Kotlin.\n\u003e ##### So your test class should look something like [THIS](producer/src/test/kotlin/com/example/demo/JavaUserDataProviderContractIT.java) if you are using Java.\n\nHaving a look at Pact-Broker UI you should see something like:\n![pact uploaded](documentation/ui-uploaded-and-verified.png)\n\nWhen clicking on an arrow in the **Pact-Brokers** network graph overview you'll see a detailed view describing the exact properties \na certain consumer relies on regarding the producers API. \nWhich is really great from Producers point of view to know it's consumers and furthermore what data they are consuming in detail.\n\n![broker-network-graph](documentation/broker-pact-details-consumer-ui.png)\n\n# _Spring Cloud Contract_ meets Pact\n\nSo far we saw different possibilities on doing consumer driven contract testing using Pact. But on the one hand you don't always know\nyour consumers (until they wrote a contract test) and on the other hand it's not nice to dictate a library or framework\nto your consumers. Assuming every application (including the maintainers) has to work with a certain tool doesn't sounds like a good idea regarding independent\nand autonomously working teams. Now the good news, [Spring-Cloud-Contract](https://spring.io/projects/spring-cloud-contract) has \nsupport for Pact by generating Pact-Files if wanted, which can of course be published to a Pact broker.\n\n## The Consumer\n\nmore coming soon ...\n\n## The Provider\n\nFirst let's add the Spring Cloud Contract maven plugin and set it up to use our \n**Pact Broker** as its Contract repository.\n\n``` xml\n\u003cplugin\u003e\n\t\u003cgroupId\u003eorg.springframework.cloud\u003c/groupId\u003e\n\t\u003cartifactId\u003espring-cloud-contract-maven-plugin\u003c/artifactId\u003e\n\t\u003cversion\u003e2.0.2.RELEASE\u003c/version\u003e\n\t\u003cextensions\u003etrue\u003c/extensions\u003e\n\t\u003cconfiguration\u003e\n\t\t\u003ccontractsRepositoryUrl\u003epact://http://localhost:80\u003c/contractsRepositoryUrl\u003e\n\n\t\t\u003c!-- We reuse the contract dependency section to set up the path\n\t\tto the folder that contains the contract definitions. In our case the\n\t\tpath will be /groupId/artifactId/version/contracts --\u003e\n\t\t\u003ccontractDependency\u003e\n\t\t\t\u003cgroupId\u003e${project.groupId}\u003c/groupId\u003e\n\t\t\t\u003cartifactId\u003e${project.artifactId}\u003c/artifactId\u003e\n\t\t\t\u003c!-- When + is passed, a latest tag will be applied when fetching pacts --\u003e\n\t\t\t\u003cversion\u003e+\u003c/version\u003e\n\t\t\u003c/contractDependency\u003e\n\n\t\t\u003c!-- The contracts mode can't be classpath --\u003e\n\t\t\u003ccontractsMode\u003eREMOTE\u003c/contractsMode\u003e\n\t\u003c/configuration\u003e\n\t\u003c!-- Don't forget to add spring-cloud-contract-pact to the classpath! --\u003e\n\t\u003cdependencies\u003e\n\t\t\u003cdependency\u003e\n\t\t\t\u003cgroupId\u003eorg.springframework.cloud\u003c/groupId\u003e\n\t\t\t\u003cartifactId\u003espring-cloud-contract-pact\u003c/artifactId\u003e\n\t\t\t\u003cversion\u003e2.0.2.RELEASE\u003c/version\u003e\n\t\t\u003c/dependency\u003e\n\t\u003c/dependencies\u003e\n\u003c/plugin\u003e\n```\n\nmore coming soon ...\n\n# Messaging Example\n\nThis is basically working the exact same way as our [REST-example](#rest-example-server-to-server-communication).\nHow does that make sense? It's because of Pact is not going to start a\nKafka, ActiveMQ or whatever mock. When talking about consumer driven contract tests with Pact and messaging\nit's about to make sure you can deserialize an events payload - describe how the messages have to look like for your consumer. \n\n**Let's start by defining our contract on the Consumer side again**\n\n#### prerequisites\nFirst let's add the relevant **Pact** dependency to the consumer applications *pom.xml*.\n\n``` xml\n\u003cdependency\u003e\n\t\u003cgroupId\u003eau.com.dius\u003c/groupId\u003e\n\t\u003cartifactId\u003epact-jvm-consumer-java8_2.12\u003c/artifactId\u003e\n\t\u003cversion\u003e3.5.21\u003c/version\u003e\n\t\u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\n## The Consumer\n\nYou'll find a working example in [MessagingContractTest](consumer/src/test/kotlin/com/example/demo/MessagingContractTest.kt) class.\nMore documentation coming soon ...\n\n## The Provider\n\nmore coming soon ...\n\n----------------\n\n### Extra infos on Pact\n#### [Terminology](https://docs.pact.io/terminology)\n\n##### Service Consumer\nA component that initiates a HTTP request to another component \n(the service provider). Note that this does not depend on the way the \ndata flows - whether it is a `GET` or a `PUT` / `POST` / `PATCH` / `DELETE`, the consumer is the initiator of the HTTP request.\n\n##### Service Provider\nA server that responds to an HTTP request from another component \n(the service consumer). A service provider may have one or more HTTP endpoints, \nand should be thought of as the \"deployable unit\" - endpoints that get \ndeployed together should be considered part of the same provider.\n\n##### Mock Service Provider\nUsed by tests in the consumer project to mock out the actual service provider, \nmeaning that integration-like tests can be run without requiring the actual \nservice provider to be available.\n\n##### Interaction\nA request and response pair. A pact consists of a collection of interactions.\n\n##### Pact file\nA file containing the JSON serialised interactions (requests and responses) \nthat were defined in the consumer tests. This is the Contract. A Pact defines:\n\n* the consumer name\n* the provider name\n* a collection of interactions\n* the pact specification version (see below)\n\n##### Pact verification\nTo verify a Pact contract, the requests contained in a Pact file are replayed \nagainst the provider code, and the responses returned are checked to ensure \nthey match those expected in the Pact file.\n\n##### Provider state\nA name describing a “state” (like a fixture) that the provider should be \nin when a given request is replayed against it - e.g. “when user John Doe \nexists” or “when user John Doe has a bank account”. These allow the same \nendpoint to be tested under different scenarios.\n\nA provider state name is specified when writing the consumer specs, then, \nwhen the pact verification is set up in the provider the same name will be \nused to identify the set up code block that should be run before the request \nis executed.\n\n##### Pact Specification\nThe Pact Specification is a document that governs the structure of the actual \ngenerated Pact files to allow for interoperability between languages \n(consider, for example, a JavaScript consumer connecting to a Scala JVM-based \nprovider) , using semantic versioning to indicate breaking changes.\n\nEach language implementation of Pact needs to implement the rules of this \nspecification, and advertise which version(s) are supported, corresponding \nclosely to which features are available.\n\n## HELPFUL LINKS\n* [https://www.martinfowler.com/articles/consumerDrivenContracts.html](https://www.martinfowler.com/articles/consumerDrivenContracts.html)\n* [https://docs.pact.io](https://docs.pact.io)\n* [https://github.com/DiUS/pact-jvm](https://github.com/DiUS/pact-jvm)\n* [https://github.com/pact-foundation/pact_broker](https://github.com/pact-foundation/pact_broker)\n* [https://github.com/pact-foundation/pact-js](https://github.com/pact-foundation/pact-js)\n* [https://www.schibsted.pl/blog/contract-testing](https://www.schibsted.pl/blog/contract-testing/)\n* [https://devblog.xero.com/trust-but-verify-using-pact-for-contract-testing-495a1e303a6](https://devblog.xero.com/trust-but-verify-using-pact-for-contract-testing-495a1e303a6)\n* [https://reflectoring.io/7-reasons-for-consumer-driven-contracts](https://reflectoring.io/7-reasons-for-consumer-driven-contracts/)\n* [https://www.slideshare.net/paucls/consumerdriven-contract-testing](https://www.slideshare.net/paucls/consumerdriven-contract-testing)\n* [https://medium.com/techbeatscorner/consumer-driven-contracts-with-pact-jvm-and-groovy-e329196e4dd](https://medium.com/techbeatscorner/consumer-driven-contracts-with-pact-jvm-and-groovy-e329196e4dd)\n* [https://www.baeldung.com/pact-junit-consumer-driven-contracts](https://www.baeldung.com/pact-junit-consumer-driven-contracts)\n* [https://kreuzwerker.de/blog/writing-contract-tests-with-pact-in-spring-boot](https://kreuzwerker.de/blog/writing-contract-tests-with-pact-in-spring-boot)\n* [https://blog.shanelee.name/2016/07/19/consumer-driven-contract-testing-using-pact/](https://blog.shanelee.name/2016/07/19/consumer-driven-contract-testing-using-pact/)\n* [https://ordina-jworks.github.io/spring/2018/04/28/Spring-Cloud-Contract-meet-Pact.html](https://ordina-jworks.github.io/spring/2018/04/28/Spring-Cloud-Contract-meet-Pact.html)\n* [https://reflectoring.io/consumer-driven-contract-provider-spring-cloud-contract](https://reflectoring.io/consumer-driven-contract-provider-spring-cloud-contract)\n* [https://cloud.spring.io/spring-cloud-contract/single/spring-cloud-contract.html#_can_i_use_the_pact_broker](https://cloud.spring.io/spring-cloud-contract/single/spring-cloud-contract.html#_can_i_use_the_pact_broker)\n* [https://cloud.spring.io/spring-cloud-contract/single/spring-cloud-contract.html#pact-converter](https://cloud.spring.io/spring-cloud-contract/single/spring-cloud-contract.html#pact-converter)\n* [https://www.youtube.com/watch?v=sAAklvxmPmk](https://www.youtube.com/watch?v=sAAklvxmPmk)\n* [http://blog.pact.io/2018/07/24/contract-testing-a-graphql-api](http://blog.pact.io/2018/07/24/contract-testing-a-graphql-api/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchristian-draeger%2Fpact-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchristian-draeger%2Fpact-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchristian-draeger%2Fpact-example/lists"}