6. Generating Stubs using RestDocs
Prev |  | Next

# 6. Generating Stubs using RestDocs

Spring RestDocs can be used to generate documentation (e.g. in asciidoctor format) for an HTTP API with Spring MockMvc or Rest Assured. At the same time as you generate documentation for your API, you can also generate WireMock stubs, by using Spring Cloud Contract WireMock. Just write your normal RestDocs test cases and use `@AutoConfigureRestDocs` to have stubs automatically in the restdocs output directory. For example:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    @AutoConfigureRestDocs(outputDir = "target/snippets")
    @AutoConfigureMockMvc
    public class ApplicationTests {

    	@Autowired
    	private MockMvc mockMvc;

    	@Test
    	public void contextLoads() throws Exception {
    		mockMvc.perform(get("/resource"))
    				.andExpect(content().string("Hello World"))
    				.andDo(document("resource"));
    	}
    }

From this test will be generated a WireMock stub at "target/snippets/stubs/resource.json". It matches all GET requests to the "/resource" path.

Without any additional configuration this will create a stub with a request matcher for the HTTP method and all headers except "host" and "content-length". To match the request more precisely, for example to match the body of a POST or PUT, we need to explicitly create a request matcher. This will do two things: 1) create a stub that only matches the way you specify, 2) assert that the request in the test case also matches the same conditions.

The main entry point for this is `WireMockRestDocs.verify()` which can be used as a substitute for the `document()` convenience method. For example:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    @AutoConfigureRestDocs(outputDir = "target/snippets")
    @AutoConfigureMockMvc
    public class ApplicationTests {

    	@Autowired
    	private MockMvc mockMvc;

    	@Test
    	public void contextLoads() throws Exception {
    		mockMvc.perform(post("/resource")
                    .content("{\"id\":\"123456\",\"message\":\"Hello World\"}"))
    				.andExpect(status().isOk())
    				.andDo(verify().jsonPath("$.id")
                            .stub("resource"));
    	}
    }

So this contract is saying: any valid POST with an "id" field will get back an the same response as in this test. You can chain together calls to `.jsonPath()` to add additional matchers. The JayWay documentation can help you to get up to speed with JSON Path if it is unfamiliar to you.

Instead of the `jsonPath` and `contentType` convenience methods, you can also use the WireMock APIs to verify the request matches the created stub. Example:

    @Test
    public void contextLoads() throws Exception {
    	mockMvc.perform(post("/resource")
                   .content("{\"id\":\"123456\",\"message\":\"Hello World\"}"))
    			.andExpect(status().isOk())
    			.andDo(verify()
    					.wiremock(WireMock.post(
    						urlPathEquals("/resource"))
    						.withRequestBody(matchingJsonPath("$.id"))
                           .stub("post-resource"));
    }

The WireMock API is rich - you can match headers, query parameters, and request body by regex as well as by json path - so this can useful to create stubs with a wider range of parameters. The above example will generate a stub something like this:

post-resource.json.

    {
      "request" : {
        "url" : "/resource",
        "method" : "POST",
        "bodyPatterns" : [ {
          "matchesJsonPath" : "$.id"
        }]
      },
      "response" : {
        "status" : 200,
        "body" : "Hello World",
        "headers" : {
          "X-Application-Context" : "application:-1",
          "Content-Type" : "text/plain"
        }
      }
    }

| Note
You can use either the `wiremock()` method or the `jsonPath()` and `contentType()` methods to create request matchers, but not both.

On the consumer side, you can make the `resource.json` generated above available on the classpath (by publishing stubs as JARs for example). After that, you can create a stub using WireMock in a number of different ways, including as described above using `@AutoConfigureWireMock(stubs="classpath:resource.json")`.

Prev |  | Next
5. WireMock and Spring MVC Mocks | Home | 7. Generating Contracts using RestDocs