Updated docs (#48)
* Added docs + tests for spec * Updated WireMock tests for docs * Made wiremock tests dynamic
This commit is contained in:
committed by
GitHub
parent
cc1d20c91b
commit
70acffd9e6
121
README.adoc
121
README.adoc
@@ -13,10 +13,125 @@ and consumers, for HTTP and message-based interactions.
|
||||
|
||||
=== Spring Cloud Contract WireMock
|
||||
|
||||
Modules giving you the possibility to use http://wiremock.org[WireMock] with different servers. Check out the
|
||||
https://github.com/spring-cloud/spring-cloud-contract/tree/master/samples[samples] for more information.
|
||||
:core_path: ../../../..
|
||||
:doc_samples: {core_path}/samples/wiremock-jetty
|
||||
|
||||
Currently we support Jetty, Native WireMock server, Tomcat and Undertow.
|
||||
Modules giving you the possibility to use
|
||||
http://wiremock.org[WireMock] with different servers by using the
|
||||
"ambient" server embedded in a Spring Boot application. Check out the
|
||||
https://github.com/spring-cloud/spring-cloud-contract/tree/master/samples[samples]
|
||||
for more details.
|
||||
|
||||
If you have a Spring Boot application that uses Tomcat as an embedded
|
||||
server, for example (the default with `spring-boot-starter-web`), then
|
||||
you can simply add `spring-cloud-contract-wiremock` to your classpath
|
||||
and add `@AutoConfigureWireMock` in order to be able to use Wiremock
|
||||
in your tests. Wiremock runs as a stub server and you can register
|
||||
stub behaviour using a Java API or via static JSON declarations as
|
||||
part of your test. Here's a simple example:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
@AutoConfigureWireMock(port = 0)
|
||||
public class WiremockForDocsTests {
|
||||
// A service that calls out over HTTP
|
||||
@Autowired private Service service;
|
||||
|
||||
// Using the WireMock APIs in the normal way:
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
// Stubbing WireMock
|
||||
stubFor(get(urlEqualTo("/resource"))
|
||||
.willReturn(aResponse().withHeader("Content-Type", "text/plain").withBody("Hello World!")));
|
||||
// We're asserting if WireMock responded properly
|
||||
assertThat(this.service.go()).isEqualTo("Hello World!");
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
To start the stub server on a different port use `@AutoConfigureWireMock(port=9999)` (for example), and for a random port use the value 0. The stub server port will be bindable in the test application context as "wiremock.server.port". Using `@AutoConfigureWireMock` adds a bean of type `WiremockConfiguration` to your test application context, where it will be cached in between methods and classes having the same context, just like for normal Spring integration tests.
|
||||
|
||||
For a more conventional WireMock experience, using JUnit `@Rules` to
|
||||
start and stop the server, just use the `WireMockSpring` convenience
|
||||
class to obtain an `Options` instance:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
@AutoConfigureWireMock
|
||||
public class WiremockForDocsClassRuleTests {
|
||||
|
||||
// Start WireMock on some dynamic port
|
||||
@ClassRule
|
||||
public static WireMockClassRule wiremock = new WireMockClassRule(
|
||||
WireMockSpring.options().dynamicPort());
|
||||
// A service that calls out over HTTP to localhost:${wiremock.port}
|
||||
@Autowired
|
||||
private Service service;
|
||||
|
||||
// Using the WireMock APIs in the normal way:
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
// Stubbing WireMock
|
||||
wiremock.stubFor(get(urlEqualTo("/resource"))
|
||||
.willReturn(aResponse().withHeader("Content-Type", "text/plain").withBody("Hello World!")));
|
||||
// We're asserting if WireMock responded properly
|
||||
assertThat(this.service.go()).isEqualTo("Hello World!");
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
The use `@ClassRule` means that the server will shut down after all the methods in this class.
|
||||
|
||||
== WireMock and Spring MVC Mocks
|
||||
|
||||
Spring Cloud Contract provides a convenience class that can load JSON WireMock stubs into a
|
||||
Spring `MockRestServiceServer`. Here's an example:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment=WebEnvironment.NONE)
|
||||
public class WiremockForDocsMockServerApplicationTests {
|
||||
|
||||
@Autowired
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Autowired
|
||||
private Service service;
|
||||
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
// will read stubs from default /resources/stubs location
|
||||
MockRestServiceServer server = WireMockExpectations.with(this.restTemplate)
|
||||
.baseUrl("http://example.org")
|
||||
.expect("resource");
|
||||
// We're asserting if WireMock responded properly
|
||||
assertThat(this.service.go()).isEqualTo("Hello World");
|
||||
server.verify();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
The `baseUrl` is prepended to all mock calls, and the `expect()`
|
||||
method takes a stub name as an argument, where the stubs are stored in
|
||||
the classpath at `/stubs/<name>.json` by default. So in this example
|
||||
the stub defined at `/stubs/resource.json` is loaded into the mock
|
||||
server, so if the `RestTemplate` is asked to visit
|
||||
`http://example.org/` it will get the responses as declared there. The
|
||||
JSON format is the normal WireMock format which you can read about in
|
||||
the WireMock website.
|
||||
|
||||
Currently we support Tomcat, Jetty and Undertow as Spring Boot
|
||||
embedded servers, and Wiremock itself has "native" support for a
|
||||
particular version of Jetty (currently 9.2). To use the native Jetty
|
||||
you need to add the native wiremock dependencies and exclude the
|
||||
Spring Boot container if there is one.
|
||||
|
||||
=== Spring Cloud Contract Verifier
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
:core_path: ../../../..
|
||||
:doc_samples: {core_path}/samples/wiremock-jetty
|
||||
|
||||
Modules giving you the possibility to use
|
||||
http://wiremock.org[WireMock] with different servers by using the
|
||||
"ambient" server embedded in a Spring Boot application. Check out the
|
||||
@@ -14,24 +17,8 @@ part of your test. Here's a simple example:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
@AutoConfigureWireMock
|
||||
public class WiremockImportApplicationTests {
|
||||
|
||||
// A service that calls out over HTTP to localhost:8080
|
||||
@Autowired
|
||||
private Service service;
|
||||
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
// Using the WireMock APIs in the normal way:
|
||||
stubFor(get(urlEqualTo("/resource"))
|
||||
.willReturn(aResponse().withHeader("Content-Type", "text/plain").withBody("Hello World!")));
|
||||
assertThat(this.service.go()).isEqualTo("Hello World!");
|
||||
}
|
||||
|
||||
}
|
||||
include::{doc_samples}/src/test/java/com/example/WiremockForDocsTests.java[tags=wiremock_test1]
|
||||
include::{doc_samples}/src/test/java/com/example/WiremockForDocsTests.java[tags=wiremock_test2]
|
||||
----
|
||||
|
||||
To start the stub server on a different port use `@AutoConfigureWireMock(port=9999)` (for example), and for a random port use the value 0. The stub server port will be bindable in the test application context as "wiremock.server.port". Using `@AutoConfigureWireMock` adds a bean of type `WiremockConfiguration` to your test application context, where it will be cached in between methods and classes having the same context, just like for normal Spring integration tests.
|
||||
@@ -42,34 +29,20 @@ class to obtain an `Options` instance:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@ClassRule
|
||||
public static WireMockClassRule wiremock = new WireMockClassRule(
|
||||
WireMockSpring.options());
|
||||
include::{doc_samples}/src/test/java/com/example/WiremockForDocsClassRuleTests.java[tags=wiremock_test1]
|
||||
include::{doc_samples}/src/test/java/com/example/WiremockForDocsClassRuleTests.java[tags=wiremock_test2]
|
||||
----
|
||||
|
||||
The use `@ClassRule` means that the server will shut down after all the methods in this class.
|
||||
|
||||
== WireMock and Spring MVC Mocks
|
||||
|
||||
Spring Cloud Contract provides a convenience class that can load JSON WireMock stubs into a Spring `MockRestServiceServer`. Here's an example:
|
||||
Spring Cloud Contract provides a convenience class that can load JSON WireMock stubs into a
|
||||
Spring `MockRestServiceServer`. Here's an example:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Autowired
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Autowired
|
||||
private Service service;
|
||||
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
MockRestServiceServer server = WireMockExpectations.with(this.restTemplate)
|
||||
.baseUrl("http://example.org")
|
||||
.expect("resource");
|
||||
assertThat(this.service.go()).isEqualTo("Hello World");
|
||||
server.verify();
|
||||
}
|
||||
|
||||
include::{doc_samples}/src/test/java/com/example/WiremockForDocsMockServerApplicationTests.java[tags=wiremock_test]
|
||||
----
|
||||
|
||||
The `baseUrl` is prepended to all mock calls, and the `expect()`
|
||||
|
||||
@@ -52,4 +52,12 @@ class Service {
|
||||
public String go() {
|
||||
return this.restTemplate.getForEntity(this.base + "/resource", String.class).getBody();
|
||||
}
|
||||
|
||||
public String getBase() {
|
||||
return base;
|
||||
}
|
||||
|
||||
public void setBase(String base) {
|
||||
this.base = base;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.example;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
|
||||
import org.springframework.cloud.contract.wiremock.WireMockSpring;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import com.github.tomakehurst.wiremock.junit.WireMockClassRule;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.get;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@ActiveProfiles("classrule")
|
||||
@DirtiesContext
|
||||
//tag::wiremock_test1[]
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
@AutoConfigureWireMock
|
||||
public class WiremockForDocsClassRuleTests {
|
||||
|
||||
// Start WireMock on some dynamic port
|
||||
@ClassRule
|
||||
public static WireMockClassRule wiremock = new WireMockClassRule(
|
||||
WireMockSpring.options().dynamicPort());
|
||||
//end::wiremock_test1[]
|
||||
@Before
|
||||
public void setup() {
|
||||
this.service.setBase("http://localhost:" + wiremock.port());
|
||||
}
|
||||
//tag::wiremock_test2[]
|
||||
// A service that calls out over HTTP to localhost:${wiremock.port}
|
||||
@Autowired
|
||||
private Service service;
|
||||
|
||||
// Using the WireMock APIs in the normal way:
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
// Stubbing WireMock
|
||||
wiremock.stubFor(get(urlEqualTo("/resource"))
|
||||
.willReturn(aResponse().withHeader("Content-Type", "text/plain").withBody("Hello World!")));
|
||||
// We're asserting if WireMock responded properly
|
||||
assertThat(this.service.go()).isEqualTo("Hello World!");
|
||||
}
|
||||
|
||||
}
|
||||
//end::wiremock_test2[]
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.example;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.cloud.contract.wiremock.WireMockExpectations;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DirtiesContext
|
||||
//tag::wiremock_test[]
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment=WebEnvironment.NONE)
|
||||
public class WiremockForDocsMockServerApplicationTests {
|
||||
|
||||
@Autowired
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Autowired
|
||||
private Service service;
|
||||
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
// will read stubs from default /resources/stubs location
|
||||
MockRestServiceServer server = WireMockExpectations.with(this.restTemplate)
|
||||
.baseUrl("http://example.org")
|
||||
.expect("resource");
|
||||
// We're asserting if WireMock responded properly
|
||||
assertThat(this.service.go()).isEqualTo("Hello World");
|
||||
server.verify();
|
||||
}
|
||||
}
|
||||
//end::wiremock_test[]
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.example;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.get;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@ActiveProfiles("docs")
|
||||
@DirtiesContext
|
||||
//tag::wiremock_test1[]
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
@AutoConfigureWireMock(port = 0)
|
||||
public class WiremockForDocsTests {
|
||||
//end::wiremock_test1[]
|
||||
|
||||
@Autowired Environment environment;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
service.setBase("http://localhost:" + this.environment.getProperty("wiremock.server.port"));
|
||||
}
|
||||
//tag::wiremock_test2[]
|
||||
// A service that calls out over HTTP
|
||||
@Autowired private Service service;
|
||||
|
||||
// Using the WireMock APIs in the normal way:
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
// Stubbing WireMock
|
||||
stubFor(get(urlEqualTo("/resource"))
|
||||
.willReturn(aResponse().withHeader("Content-Type", "text/plain").withBody("Hello World!")));
|
||||
// We're asserting if WireMock responded properly
|
||||
assertThat(this.service.go()).isEqualTo("Hello World!");
|
||||
}
|
||||
|
||||
}
|
||||
//end::wiremock_test2[]
|
||||
@@ -0,0 +1 @@
|
||||
app.baseUrl: http://localhost:9090
|
||||
@@ -0,0 +1 @@
|
||||
app.baseUrl: http://localhost:8080
|
||||
4
spring-cloud-contract-spec/README.adoc
Normal file
4
spring-cloud-contract-spec/README.adoc
Normal file
@@ -0,0 +1,4 @@
|
||||
=== Spring Cloud Contract Specification
|
||||
|
||||
This module contains the specifications describing contracts. Currently we have only
|
||||
one way for contract description which is the Groovy DSL.
|
||||
@@ -0,0 +1,80 @@
|
||||
package org.springframework.cloud.contract.spec.internal
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import spock.lang.Specification
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
class ContractSpec extends Specification {
|
||||
|
||||
def 'should work for http'() {
|
||||
when:
|
||||
Contract.make {
|
||||
request {
|
||||
url('/foo')
|
||||
method('PUT')
|
||||
headers {
|
||||
header([
|
||||
foo: 'bar'
|
||||
])
|
||||
}
|
||||
body([
|
||||
foo: 'bar'
|
||||
])
|
||||
}
|
||||
response {
|
||||
headers {
|
||||
header([
|
||||
foo2: 'bar'
|
||||
])
|
||||
}
|
||||
body([
|
||||
foo2: 'bar'
|
||||
])
|
||||
}
|
||||
}
|
||||
then:
|
||||
noExceptionThrown()
|
||||
}
|
||||
def 'should work for messaging'() {
|
||||
when:
|
||||
Contract.make {
|
||||
input {
|
||||
messageFrom('input')
|
||||
messageBody([
|
||||
foo: 'bar'
|
||||
])
|
||||
messageHeaders {
|
||||
header([
|
||||
foo: 'bar'
|
||||
])
|
||||
}
|
||||
}
|
||||
outputMessage {
|
||||
sentTo('output')
|
||||
body([
|
||||
foo2: 'bar'
|
||||
])
|
||||
headers {
|
||||
header([
|
||||
foo2: 'bar'
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
then:
|
||||
noExceptionThrown()
|
||||
}
|
||||
|
||||
def 'should generate a value if only regex is passed for client'() {
|
||||
given:
|
||||
Request request = new Request()
|
||||
DslProperty property
|
||||
when:
|
||||
request.with {
|
||||
property = value(consumer(regex("[0-9]{5}")))
|
||||
}
|
||||
then:
|
||||
(property.serverValue as String).matches(/[0-9]{5}/)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user