Skip to content
This repository has been archived by the owner on Jun 7, 2021. It is now read-only.

Commit

Permalink
Added an example for consumer driven contracts
Browse files Browse the repository at this point in the history
commit 7f8b0c57480b86048692c2e15f2538224defdb8a
Author: Heiko Braun <ike.braun@googlemail.com>
Date:   Fri Dec 4 10:09:40 2015 +0100

    Added a readme for the consumer driven contracts

commit cb977753f7b82944319bb42e738d9c44e33cb8cf
Author: Heiko Braun <ike.braun@googlemail.com>
Date:   Fri Dec 4 09:44:37 2015 +0100

    Group pact examples in custom module

commit 6c32fa501b7023d547b80064e70ebc78d08be592
Author: Heiko Braun <ike.braun@googlemail.com>
Date:   Fri Dec 4 09:44:22 2015 +0100

    Cleanup pact examples

commit 9c68fbf83da18e875cd10dd30fff785724c4ce2e
Author: Heiko Braun <ike.braun@googlemail.com>
Date:   Fri Dec 4 09:35:23 2015 +0100

    first roundtrip  example

commit a3b91e60bca07713eb50e43771e367162858dd0f
Author: Heiko Braun <ike.braun@googlemail.com>
Date:   Thu Dec 3 17:24:04 2015 +0100

    Simplified pact API usage

commit 5da28fb9c14ada142db2108b02e3bdbfff24cb71
Author: Heiko Braun <ike.braun@googlemail.com>
Date:   Thu Dec 3 15:31:50 2015 +0100

    Added a consumer contract test example

commit e1bfdd8f389bc48bc5857e2d053b3b6fc22b08f8
Author: Heiko Braun <ike.braun@googlemail.com>
Date:   Thu Dec 3 15:10:40 2015 +0100

    Added contract based test example
  • Loading branch information
heiko-braun committed Dec 4, 2015
1 parent 8aba854 commit 9db7168
Show file tree
Hide file tree
Showing 14 changed files with 550 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -12,3 +12,5 @@ build/
# verify logs
verify.log
log
jaxrs/.DS_Store
.DS_Store
100 changes: 100 additions & 0 deletions jaxrs/contract-based-testing/README.md
@@ -0,0 +1,100 @@
# Contract based testing example

This is an example that demonstrates how consumer driven contracts can be used to verify the contract between a service consumer and a service provider.

If you are not familiar with contract based testing and consumer driven tests in particular, we recommend the excellent Thoughtworks article, that explains the ideas in great detail: http://martinfowler.com/articles/consumerDrivenContracts.html

## Example Layout

The example breaks into two parts:

**Service consumer part**

The consumer verifies it's own service interaction patterns against a mock service as part of it's unit or integration test runs (See `ConsumerTest.java`).

Upon successful completion of the consumer tests, a consumer contract definition is created:

```
{
"provider": {
"name": "MyProvider"
},
"consumer": {
"name": "MyConsumer"
},
"interactions": [
{
"providerState": "Consumer is FOOBAR",
"description": "A request to say Howdy",
"request": {
"method": "POST",
"path": "/",
"headers": {
"client-name": "FOOBAR"
}
},
"response": {
"status": 200,
"body": "Howdy FOOBAR"
}
}
],
"metadata": {
"pact-specification": {
"version": "2.0.0"
},
"pact-jvm": {
"version": "3.2.0"
}
}
}
```
(Taken from `jaxrs-consumer/target/pacts`)

**The service provider part**

The consumer contract definition (`MyConsumer-MyProvider.json`) is shared with the provider. The provider uses this contract to replay the consumer service interaction against it's service implementation.

In this example, it happens through the pact-jvm maven plugin (See `jaxrs-provider/pom.xml`)


```
[INFO]
[INFO] --- pact-jvm-provider-maven_2.11:3.2.0:verify (verify-pacts) @ example-jaxrs-cdc-provider ---
Loading pact files for provider MyProvider from /Users/hbraun/dev/prj/wildfly-swarm-examples/jaxrs/contract-based-testing/jaxrs-provider/src/pacts
Found 1 pact files
Verifying a pact between MyConsumer and MyProvider
[Using file /Users/hbraun/dev/prj/wildfly-swarm-examples/jaxrs/contract-based-testing/jaxrs-provider/src/pacts/MyConsumer-MyProvider.json]
Given Consumer is FOOBAR
A request to say Howdy
returns a response which
has status code 200 (OK)
has a matching body (OK)
```

## Executing the tests

To run the full cycle of tests, move to the top level directory and execute the integration tests:

```
cd contract-based-testing
mvn clean verify
```

These steps can also be executed for the consumer and provider separately:

```
cd [jaxrs-consumer|jaxrs-provider]
mvn clean verify
```

> **NOTE**: The examples do leverage the maven failsafe plugin. As such it's important execute the `verify` goal, opposed to the other lifecycles of the plugin. `verify` ensures that are relevant steps are executed to teardown the server and cleanup resource references.

## Further resources

- pact-jvm: https://github.com/DiUS/pact-jvm
- consumer driven contracts : http://martinfowler.com/articles/consumerDrivenContracts.html
88 changes: 88 additions & 0 deletions jaxrs/contract-based-testing/jaxrs-consumer/pom.xml
@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015 Red Hat, Inc. and/or its affiliates.
~
~ Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.wildfly.swarm.examples</groupId>
<artifactId>examples-jaxrs-cdc</artifactId>
<version>1.0.0.Alpha6-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>

<artifactId>example-jaxrs-cdc-consumer</artifactId>

<name>WildFly Swarm Examples: JAX-RS Contracts: Consumer Example</name>
<description>Demonstrates how service consumers creates and verify pact files.</description>

<packaging>war</packaging>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<packagingExcludes>WEB-INF/lib/wildfly-swarm-*.jar</packagingExcludes>
</configuration>
</plugin>
<plugin>
<groupId>org.wildfly.swarm</groupId>
<artifactId>wildfly-swarm-plugin</artifactId>
<executions>
<execution>
<id>package</id>
</execution>
<execution>
<id>start</id>
</execution>
<execution>
<id>stop</id>
</execution>
</executions>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>org.wildfly.swarm.examples</groupId>
<artifactId>examples-base</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>wildfly-swarm-jaxrs</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>au.com.dius</groupId>
<artifactId>pact-jvm-consumer-junit_2.11</artifactId>
<version>3.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>fluent-hc</artifactId>
<version>4.5.1</version>
<scope>test</scope>
</dependency>
</dependencies>

</project>
@@ -0,0 +1,54 @@
package org.wildfly.swarm.it.jaxrs;

import au.com.dius.pact.consumer.ConsumerPactTest;
import au.com.dius.pact.consumer.dsl.PactDslWithProvider;
import au.com.dius.pact.model.PactFragment;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import static org.junit.Assert.assertEquals;

/**
* Declares the expected interactions and starts a mock server.
* The actual client code is then tested in {@link #runTest(String)}.
*
* @author Heiko Braun
* @since 03/12/15
*/
public class ConsumerTest extends ConsumerPactTest {

@Override
protected PactFragment createFragment(PactDslWithProvider builder) {
Map<String,String> requestHeader = new HashMap<>();
requestHeader.put("client-name", "FOOBAR");

return builder
.given("Consumer is FOOBAR")
.uponReceiving("A request to say Howdy")
.path("/")
.method("POST")
.headers(requestHeader)
.willRespondWith()
.status(200)
.body("Howdy FOOBAR")
.toFragment();
}


@Override
protected String providerName() {
return "MyProvider";
}

@Override
protected String consumerName() {
return "MyConsumer";
}

@Override
protected void runTest(String url) throws IOException {
assertEquals(new ProviderClient(url).hello("FOOBAR"), "Howdy FOOBAR");
}
}
@@ -0,0 +1,28 @@
package org.wildfly.swarm.it.jaxrs;

import org.apache.http.client.fluent.Request;

import java.io.IOException;

/**
* An example client component that invokes on a service.
* @author Heiko Braun
* @since 03/12/15
*/
public class ProviderClient {

private final String url;

public ProviderClient(String url) {
this.url = url;
}

public String hello(String name) throws IOException {
String response = Request.Post(url + "/")
.addHeader("client-name", name)
.execute()
.returnContent()
.asString();
return response;
}
}
@@ -0,0 +1,14 @@
package org.wildfly.swarm.examples.jaxrs;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

/**
* @author Bob McWhirter
*/
@ApplicationPath("/")
public class MyApplication extends Application {

public MyApplication() {
}
}
@@ -0,0 +1,19 @@
package org.wildfly.swarm.examples.jaxrs;

import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

/**
* @author Heiko Braun
*/
@Path("/")
public class MyResource {

@POST
@Produces("text/plain")
public String getName(@HeaderParam("client-name") String name) {
return "Howdy " + name;
}
}

0 comments on commit 9db7168

Please sign in to comment.