Add support for documenting a portion of a request or response payload

Closes gh-312
This commit is contained in:
Andy Wilkinson
2016-10-27 10:16:46 +01:00
parent 60211dab86
commit 7bcfbd9e35
16 changed files with 1425 additions and 32 deletions

View File

@@ -402,6 +402,69 @@ include::{examples-dir}/com/example/restassured/Payload.java[tags=book-array]
<1> Document the array
<2> Document `[].title` and `[].author` using the existing descriptors prefixed with `[].`
[[documenting-your-api-request-response-payloads-subsections]]
==== Documenting a portion of a request or response payload
If a payload is large or structurally complex, it can be useful to document
individual sections of the payload. REST Docs allows you to do so by extracting a
subsection of the payload and then documenting it.
Consider the following JSON response payload:
[source,json,indent=0]
----
{
"weather": {
"wind": {
"speed": 15.3,
"direction": 287.0
},
"temperature": {
"high": 21.2,
"low": 14.8
}
}
}
----
A snippet that documents the fields of the `temperature` object (`high` and `low`) can
be produced as follows:
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/Payload.java[tags=subsection]
----
<1> Produce a snippet describing the fields in the subsection of the response payload
beneath the path `weather.temperature`. Uses the static `beneathPath` method on
`org.springframework.restdocs.payload.PayloadDocumentation`.
<2> Document the `high` and `low` fields.
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/Payload.java[tags=subsection]
----
<1> Produce a snippet describing the fields in the subsection of the response payload
beneath the path `weather.temperature`. Uses the static `beneathPath` method on
`org.springframework.restdocs.payload.PayloadDocumentation`.
<2> Document the `high` and `low` fields.
The result is a snippet that contains a table describing the `high` and `low` fields
of `weather.temperature`. To make the snippet's name distinct, an identifier for the
subsection is included. By default, this identifier is `beneath-${path}`. For
example, the code above will result in a snippet named
`response-fields-beneath-weather.temperature.adoc`. The identifier can be customized using
the `withSubsectionId(String)` method:
----
include::{examples-dir}/com/example/Payload.java[tags=custom-subsection-id]
----
This example will result in a snippet named `response-fields-temp.adoc`.
[[documenting-your-api-request-parameters]]
=== Request parameters

View File

@@ -18,7 +18,9 @@ package com.example;
import org.springframework.restdocs.payload.FieldDescriptor;
import static org.springframework.restdocs.payload.PayloadDocumentation.beneathPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
public class Payload {
@@ -31,4 +33,12 @@ public class Payload {
// end::book-descriptors[]
}
public void customSubsectionId() {
// tag::custom-subsection-id[]
responseFields(beneathPath("weather.temperature").withSubsectionId("temp"),
fieldWithPath("high").description(""),
fieldWithPath("low").description(""));
// end::custom-subsection-id[]
}
}

View File

@@ -16,21 +16,22 @@
package com.example.mockmvc;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;
import static org.springframework.restdocs.snippet.Attributes.attributes;
import static org.springframework.restdocs.snippet.Attributes.key;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.springframework.http.MediaType;
import org.springframework.restdocs.payload.FieldDescriptor;
import org.springframework.restdocs.payload.JsonFieldType;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
import static org.springframework.restdocs.payload.PayloadDocumentation.beneathPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.restdocs.snippet.Attributes.attributes;
import static org.springframework.restdocs.snippet.Attributes.key;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class Payload {
private MockMvc mockMvc;
@@ -91,4 +92,14 @@ public class Payload {
// end::book-array[]
}
public void subsection() throws Exception {
// tag::subsection[]
this.mockMvc.perform(get("/locations/1").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(document("location", responseFields(beneathPath("weather.temperature"), // <1>
fieldWithPath("high").description("The forecast high in degrees celcius"), // <2>
fieldWithPath("low").description("The forecast low in degrees celcius"))));
// end::subsection[]
}
}

View File

@@ -23,6 +23,7 @@ import com.jayway.restassured.RestAssured;
import com.jayway.restassured.specification.RequestSpecification;
import static org.hamcrest.CoreMatchers.is;
import static org.springframework.restdocs.payload.PayloadDocumentation.beneathPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
@@ -95,4 +96,15 @@ public class Payload {
// end::book-array[]
}
public void subsection() throws Exception {
// tag::subsection[]
RestAssured.given(this.spec).accept("application/json")
.filter(document("location", responseFields(beneathPath("weather.temperature"), // <1>
fieldWithPath("high").description("The forecast high in degrees celcius"), // <2>
fieldWithPath("low").description("The forecast low in degrees celcius"))))
.when().get("/locations/1")
.then().assertThat().statusCode(is(200));
// end::subsection[]
}
}