Provide support for documenting path parameters
This commit adds support for documenting a request's path parameters.
For example:
mockMvc.perform(
get("/locations/{latitude}/{longitude}", 51.5072, 0.1275))
.andExpect(status().isOk())
.andDo(document("locations").withPathParameters(
parameterWithName("latitude")
.description("The location's latitude"),
parameterWithName("longitude")
.description("The location's longitude")
));
Closes gh-86
This commit is contained in:
@@ -18,4 +18,5 @@ asciidoctor {
|
||||
}
|
||||
attributes 'revnumber': project.version,
|
||||
'branch-or-tag': project.version.endsWith('SNAPSHOT') ? 'master': "v${project.version}"
|
||||
inputs.files(sourceSets.test.java)
|
||||
}
|
||||
@@ -196,6 +196,32 @@ is not found in the request.
|
||||
|
||||
|
||||
|
||||
[[documenting-your-api-path-parameters]]
|
||||
=== Path parameters
|
||||
|
||||
A request's path parameters can be documented using `withPathParameters`
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::{examples-dir}/com/example/PathParameters.java[tags=path-parameters]
|
||||
----
|
||||
<1> Build the request. Uses the static `get` method on `RestDocumentationRequestBuilders`.
|
||||
<2> Use `withPathParameters` to describe the path parameters.
|
||||
<3> Document a parameter named `longitude`. Uses the static `parameterWithName` method on
|
||||
`org.springframework.restdocs.request.RequestDocumentation`.
|
||||
<4> Document a parameter named `latitude`.
|
||||
|
||||
The result is a snippet named `path-parameters.adoc` that contains a table describing
|
||||
the path parameters that are supported by the resource.
|
||||
|
||||
When documenting path parameters, the test will fail if an undocumented path parameter
|
||||
is used in the request. Similarly, the test will also fail if a documented path parameter
|
||||
is not found in the request.
|
||||
|
||||
TIP: To make the path parameters available for documentation, the request must be
|
||||
built using one of the methods on `RestDocumentationRequestBuilders` rather than
|
||||
`MockMvcRequestBuilders`.
|
||||
|
||||
[[documenting-your-api-default-snippets]]
|
||||
=== Default snippets
|
||||
|
||||
@@ -286,8 +312,8 @@ override the template for the `curl-request.adoc` snippet, create a template nam
|
||||
|
||||
There are two ways to provide extra information for inclusion in a generated snippet:
|
||||
|
||||
. Use the `attributes` method on a field, link or query parameter descriptor to add one or
|
||||
more attributes to an individual descriptor
|
||||
. Use the `attributes` method on a field, link or parameter descriptor to add one or more
|
||||
attributes to an individual descriptor.
|
||||
. Pass in some attributes when calling `withCurlRequest`, `withHttpRequest`,
|
||||
`withHttpResponse`, etc on `RestDocumentationResultHandler`. Such attributes will be
|
||||
associated with the snippet as a whole.
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package com.example;
|
||||
|
||||
import static org.springframework.restdocs.RestDocumentation.document;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
|
||||
import static org.springframework.restdocs.hypermedia.LinkExtractors.halLinks;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package com.example;
|
||||
|
||||
import static org.springframework.restdocs.RestDocumentation.document;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
41
docs/src/test/java/com/example/PathParameters.java
Normal file
41
docs/src/test/java/com/example/PathParameters.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example;
|
||||
|
||||
import static org.springframework.restdocs.RestDocumentation.document;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
public class PathParameters {
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
public void pathParameters() throws Exception {
|
||||
// tag::path-parameters[]
|
||||
this.mockMvc.perform(get("/locations/{latitude}/{longitude}", 51.5072, 0.1275)) // <1>
|
||||
.andExpect(status().isOk())
|
||||
.andDo(document("locations").withPathParameters( // <2>
|
||||
parameterWithName("latitude").description("The location's latitude"), // <3>
|
||||
parameterWithName("longitude").description("The location's longitude") // <4>
|
||||
));
|
||||
// end::path-parameters[]
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,8 +20,8 @@ import static org.springframework.restdocs.RestDocumentation.document;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
@@ -18,7 +18,7 @@ package com.example;
|
||||
|
||||
import static org.springframework.restdocs.RestDocumentation.document;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package com.example;
|
||||
|
||||
import static org.springframework.restdocs.RestDocumentation.modifyResponseTo;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
@@ -22,9 +22,9 @@ import static org.springframework.restdocs.RestDocumentation.documentationConfig
|
||||
import static org.springframework.restdocs.RestDocumentation.document;
|
||||
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.patch;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
@@ -279,7 +279,7 @@ public class ApiDocumentation {
|
||||
fieldWithPath("title").description("The title of the note").type(FieldType.STRING).optional(),
|
||||
fieldWithPath("body").description("The body of the note").type(FieldType.STRING).optional(),
|
||||
fieldWithPath("tags").description("An array of tag resource URIs").optional()));
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -21,9 +21,9 @@ import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.springframework.restdocs.RestDocumentation.document;
|
||||
import static org.springframework.restdocs.RestDocumentation.documentationConfiguration;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.patch;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
@@ -155,7 +155,7 @@ public class GettingStartedDocumentation {
|
||||
return noteLocation;
|
||||
}
|
||||
|
||||
void getTags(String noteTagsLocation) throws Exception {
|
||||
void getTags(String noteTagsLocation) throws Exception {
|
||||
this.mockMvc.perform(get(noteTagsLocation))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("_embedded.tags", hasSize(1)));
|
||||
@@ -177,7 +177,7 @@ public class GettingStartedDocumentation {
|
||||
.andReturn();
|
||||
}
|
||||
|
||||
void getTagsForExistingNote(String noteTagsLocation) throws Exception {
|
||||
void getTagsForExistingNote(String noteTagsLocation) throws Exception {
|
||||
this.mockMvc.perform(get(noteTagsLocation))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("_embedded.tags", hasSize(1)));
|
||||
|
||||
@@ -22,9 +22,9 @@ import static org.springframework.restdocs.RestDocumentation.document;
|
||||
import static org.springframework.restdocs.RestDocumentation.documentationConfiguration;
|
||||
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.patch;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@@ -21,9 +21,9 @@ import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.springframework.restdocs.RestDocumentation.document;
|
||||
import static org.springframework.restdocs.RestDocumentation.documentationConfiguration;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.patch;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
@@ -155,7 +155,7 @@ public class GettingStartedDocumentation {
|
||||
return noteLocation;
|
||||
}
|
||||
|
||||
void getTags(String noteTagsLocation) throws Exception {
|
||||
void getTags(String noteTagsLocation) throws Exception {
|
||||
this.mockMvc.perform(get(noteTagsLocation))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("_embedded.tags", hasSize(1)));
|
||||
@@ -177,7 +177,7 @@ public class GettingStartedDocumentation {
|
||||
.andReturn();
|
||||
}
|
||||
|
||||
void getTagsForExistingNote(String noteTagsLocation) throws Exception {
|
||||
void getTagsForExistingNote(String noteTagsLocation) throws Exception {
|
||||
this.mockMvc.perform(get(noteTagsLocation))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("_embedded.tags", hasSize(1)));
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
/**
|
||||
* A drop-in replacement for {@link MockMvcRequestBuilders} that captures a request's URL
|
||||
* template and makes it available for documentation. Required when
|
||||
* {@link RestDocumentationResultHandler#withPathParameters(org.springframework.restdocs .request.ParameterDescriptor...)
|
||||
* documenting path parameters} and recommended for general usage.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @see MockMvcRequestBuilders
|
||||
* @see RestDocumentationResultHandler#withPathParameters(org.springframework.restdocs.request.ParameterDescriptor...)
|
||||
* @see RestDocumentationResultHandler#withPathParameters(java.util.Map,
|
||||
* org.springframework.restdocs.request.ParameterDescriptor...)
|
||||
*/
|
||||
public abstract class RestDocumentationRequestBuilders {
|
||||
|
||||
private static final String ATTRIBUTE_NAME_URL_TEMPLATE = "org.springframework.restdocs.urlTemplate";
|
||||
|
||||
private RestDocumentationRequestBuilders() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockHttpServletRequestBuilder} for a GET request. The url template
|
||||
* will be captured and made available for documentation.
|
||||
*
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param urlVariables zero or more URL variables
|
||||
* @return the builder for the GET request
|
||||
*/
|
||||
public static MockHttpServletRequestBuilder get(String urlTemplate,
|
||||
Object... urlVariables) {
|
||||
return MockMvcRequestBuilders.get(urlTemplate, urlVariables).requestAttr(
|
||||
ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockHttpServletRequestBuilder} for a GET request.
|
||||
*
|
||||
* @param uri the URL
|
||||
* @return the builder for the GET request
|
||||
*/
|
||||
public static MockHttpServletRequestBuilder get(URI uri) {
|
||||
return MockMvcRequestBuilders.get(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockHttpServletRequestBuilder} for a POST request. The url template
|
||||
* will be captured and made available for documentation.
|
||||
*
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param urlVariables zero or more URL variables
|
||||
* @return the builder for the POST request
|
||||
*/
|
||||
public static MockHttpServletRequestBuilder post(String urlTemplate,
|
||||
Object... urlVariables) {
|
||||
return MockMvcRequestBuilders.post(urlTemplate, urlVariables).requestAttr(
|
||||
ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockHttpServletRequestBuilder} for a POST request.
|
||||
*
|
||||
* @param uri the URL
|
||||
* @return the builder for the POST request
|
||||
*/
|
||||
public static MockHttpServletRequestBuilder post(URI uri) {
|
||||
return MockMvcRequestBuilders.post(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockHttpServletRequestBuilder} for a PUT request. The url template
|
||||
* will be captured and made available for documentation.
|
||||
*
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param urlVariables zero or more URL variables
|
||||
* @return the builder for the PUT request
|
||||
*/
|
||||
public static MockHttpServletRequestBuilder put(String urlTemplate,
|
||||
Object... urlVariables) {
|
||||
return MockMvcRequestBuilders.put(urlTemplate, urlVariables).requestAttr(
|
||||
ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockHttpServletRequestBuilder} for a PUT request.
|
||||
*
|
||||
* @param uri the URL
|
||||
* @return the builder for the PUT request
|
||||
*/
|
||||
public static MockHttpServletRequestBuilder put(URI uri) {
|
||||
return MockMvcRequestBuilders.put(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockHttpServletRequestBuilder} for a PATCH request. The url
|
||||
* template will be captured and made available for documentation.
|
||||
*
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param urlVariables zero or more URL variables
|
||||
* @return the builder for the PATCH request
|
||||
*/
|
||||
public static MockHttpServletRequestBuilder patch(String urlTemplate,
|
||||
Object... urlVariables) {
|
||||
return MockMvcRequestBuilders.patch(urlTemplate, urlVariables).requestAttr(
|
||||
ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockHttpServletRequestBuilder} for a PATCH request.
|
||||
*
|
||||
* @param uri the URL
|
||||
* @return the builder for the PATCH request
|
||||
*/
|
||||
public static MockHttpServletRequestBuilder patch(URI uri) {
|
||||
return MockMvcRequestBuilders.patch(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockHttpServletRequestBuilder} for a DELETE request. The url
|
||||
* template will be captured and made available for documentation.
|
||||
*
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param urlVariables zero or more URL variables
|
||||
* @return the builder for the DELETE request
|
||||
*/
|
||||
public static MockHttpServletRequestBuilder delete(String urlTemplate,
|
||||
Object... urlVariables) {
|
||||
return MockMvcRequestBuilders.delete(urlTemplate, urlVariables).requestAttr(
|
||||
ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockHttpServletRequestBuilder} for a DELETE request.
|
||||
*
|
||||
* @param uri the URL
|
||||
* @return the builder for the DELETE request
|
||||
*/
|
||||
public static MockHttpServletRequestBuilder delete(URI uri) {
|
||||
return MockMvcRequestBuilders.delete(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockHttpServletRequestBuilder} for an OPTIONS request. The url
|
||||
* template will be captured and made available for documentation.
|
||||
*
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param urlVariables zero or more URL variables
|
||||
* @return the builder for the OPTIONS request
|
||||
*/
|
||||
public static MockHttpServletRequestBuilder options(String urlTemplate,
|
||||
Object... urlVariables) {
|
||||
return MockMvcRequestBuilders.options(urlTemplate, urlVariables).requestAttr(
|
||||
ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockHttpServletRequestBuilder} for an OPTIONS request.
|
||||
*
|
||||
* @param uri the URL
|
||||
* @return the builder for the OPTIONS request
|
||||
*/
|
||||
public static MockHttpServletRequestBuilder options(URI uri) {
|
||||
return MockMvcRequestBuilders.options(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockHttpServletRequestBuilder} for a HEAD request. The url template
|
||||
* will be captured and made available for documentation.
|
||||
*
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param urlVariables zero or more URL variables
|
||||
* @return the builder for the HEAD request
|
||||
*/
|
||||
public static MockHttpServletRequestBuilder head(String urlTemplate,
|
||||
Object... urlVariables) {
|
||||
return MockMvcRequestBuilders.head(urlTemplate, urlVariables).requestAttr(
|
||||
ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockHttpServletRequestBuilder} for a HEAD request.
|
||||
*
|
||||
* @param uri the URL
|
||||
* @return the builder for the HEAD request
|
||||
*/
|
||||
public static MockHttpServletRequestBuilder head(URI uri) {
|
||||
return MockMvcRequestBuilders.head(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockHttpServletRequestBuilder} for a request with the given HTTP
|
||||
* method. The url template will be captured and made available for documentation.
|
||||
*
|
||||
* @param httpMethod the HTTP method
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param urlVariables zero or more URL variables
|
||||
* @return the builder for the request
|
||||
*/
|
||||
public static MockHttpServletRequestBuilder request(HttpMethod httpMethod,
|
||||
String urlTemplate, Object... urlVariables) {
|
||||
return MockMvcRequestBuilders.request(httpMethod, urlTemplate, urlVariables)
|
||||
.requestAttr(ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockHttpServletRequestBuilder} for a request with the given HTTP
|
||||
* method.
|
||||
* @param httpMethod the HTTP method (GET, POST, etc)
|
||||
* @param uri the URL
|
||||
* @return the builder for the request
|
||||
*/
|
||||
public static MockHttpServletRequestBuilder request(HttpMethod httpMethod, URI uri) {
|
||||
return MockMvcRequestBuilders.request(httpMethod, uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockHttpServletRequestBuilder} for a multipart request. The url
|
||||
* template will be captured and made available for documentation.
|
||||
*
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param urlVariables zero or more URL variables
|
||||
* @return the builder for the file upload request
|
||||
*/
|
||||
public static MockMultipartHttpServletRequestBuilder fileUpload(String urlTemplate,
|
||||
Object... urlVariables) {
|
||||
return (MockMultipartHttpServletRequestBuilder) MockMvcRequestBuilders
|
||||
.fileUpload(urlTemplate, urlVariables).requestAttr(
|
||||
ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockHttpServletRequestBuilder} for a multipart request.
|
||||
*
|
||||
* @param uri the URL
|
||||
* @return the builder for the file upload request
|
||||
*/
|
||||
public static MockMultipartHttpServletRequestBuilder fileUpload(URI uri) {
|
||||
return MockMvcRequestBuilders.fileUpload(uri);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import static org.springframework.restdocs.http.HttpDocumentation.documentHttpRe
|
||||
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.documentLinks;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.documentRequestFields;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.documentResponseFields;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.documentPathParameters;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.documentQueryParameters;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -309,6 +310,45 @@ public class RestDocumentationResultHandler implements ResultHandler {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Documents the parameters in the request's path using the given {@code descriptors}.
|
||||
* <p>
|
||||
* If a parameter is present in the path but is not described by one of the
|
||||
* descriptors a failure will occur when this handler is invoked. Similarly, if a
|
||||
* parameter is described but is not present in the request a failure will also occur
|
||||
* when this handler is invoked.
|
||||
*
|
||||
* @param descriptors the parameter descriptors
|
||||
* @return {@code this}
|
||||
* @see RequestDocumentation#parameterWithName(String)
|
||||
*/
|
||||
public RestDocumentationResultHandler withPathParameters(
|
||||
ParameterDescriptor... descriptors) {
|
||||
return this.withQueryParameters(null, descriptors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Documents the parameters in the request's path using the given {@code descriptors}.
|
||||
* The given {@code attributes} are made available during the generation of the path
|
||||
* parameters snippet.
|
||||
* <p>
|
||||
* If a parameter is present in the path but is not described by one of the
|
||||
* descriptors a failure will occur when this handler is invoked. Similarly, if a
|
||||
* parameter is described but is not present in the request a failure will also occur
|
||||
* when this handler is invoked.
|
||||
*
|
||||
* @param descriptors the parameter descriptors
|
||||
* @param attributes the attributes
|
||||
* @return {@code this}
|
||||
* @see RequestDocumentation#parameterWithName(String)
|
||||
*/
|
||||
public RestDocumentationResultHandler withPathParameters(
|
||||
Map<String, Object> attributes, ParameterDescriptor... descriptors) {
|
||||
this.delegates.add(documentPathParameters(this.identifier, attributes,
|
||||
descriptors));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(MvcResult result) throws Exception {
|
||||
this.curlRequest.handle(result);
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.springframework.restdocs.request;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.restdocs.snippet.SnippetWritingResultHandler;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
public abstract class AbstractParametersSnippetResultHandler extends
|
||||
SnippetWritingResultHandler {
|
||||
|
||||
private final Map<String, ParameterDescriptor> descriptorsByName = new LinkedHashMap<>();
|
||||
|
||||
protected AbstractParametersSnippetResultHandler(String identifier,
|
||||
String snippetName, Map<String, Object> attributes,
|
||||
ParameterDescriptor... descriptors) {
|
||||
super(identifier, snippetName, attributes);
|
||||
for (ParameterDescriptor descriptor : descriptors) {
|
||||
Assert.hasText(descriptor.getName());
|
||||
Assert.hasText(descriptor.getDescription());
|
||||
this.descriptorsByName.put(descriptor.getName(), descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> doHandle(MvcResult result) throws IOException {
|
||||
verifyParameterDescriptors(result);
|
||||
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
List<Map<String, Object>> parameters = new ArrayList<>();
|
||||
for (Entry<String, ParameterDescriptor> entry : this.descriptorsByName.entrySet()) {
|
||||
parameters.add(entry.getValue().toModel());
|
||||
}
|
||||
model.put("parameters", parameters);
|
||||
return model;
|
||||
}
|
||||
|
||||
protected void verifyParameterDescriptors(MvcResult result) {
|
||||
Set<String> actualParameters = extractActualParameters(result);
|
||||
Set<String> expectedParameters = this.descriptorsByName.keySet();
|
||||
Set<String> undocumentedParameters = new HashSet<String>(actualParameters);
|
||||
undocumentedParameters.removeAll(expectedParameters);
|
||||
Set<String> missingParameters = new HashSet<String>(expectedParameters);
|
||||
missingParameters.removeAll(actualParameters);
|
||||
|
||||
if (!undocumentedParameters.isEmpty() || !missingParameters.isEmpty()) {
|
||||
verificationFailed(undocumentedParameters, missingParameters);
|
||||
}
|
||||
else {
|
||||
Assert.isTrue(actualParameters.equals(expectedParameters));
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Set<String> extractActualParameters(MvcResult result);
|
||||
|
||||
protected abstract void verificationFailed(Set<String> undocumentedParameters,
|
||||
Set<String> missingParameters);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.request;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.restdocs.snippet.SnippetGenerationException;
|
||||
import org.springframework.restdocs.snippet.SnippetWritingResultHandler;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link SnippetWritingResultHandler} that produces a snippet documenting the path
|
||||
* parameters supported by a RESTful resource.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class PathParametersSnippetResultHandler extends
|
||||
AbstractParametersSnippetResultHandler {
|
||||
|
||||
private static final Pattern NAMES_PATTERN = Pattern.compile("\\{([^/]+?)\\}");
|
||||
|
||||
protected PathParametersSnippetResultHandler(String identifier,
|
||||
Map<String, Object> attributes, ParameterDescriptor... descriptors) {
|
||||
super(identifier, "path-parameters", attributes, descriptors);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<String> extractActualParameters(MvcResult result) {
|
||||
String urlTemplate = extractUrlTemplate(result);
|
||||
Matcher matcher = NAMES_PATTERN.matcher(urlTemplate);
|
||||
Set<String> actualParameters = new HashSet<>();
|
||||
while (matcher.find()) {
|
||||
String match = matcher.group(1);
|
||||
actualParameters.add(getParameterName(match));
|
||||
}
|
||||
return actualParameters;
|
||||
}
|
||||
|
||||
private String extractUrlTemplate(MvcResult result) {
|
||||
String urlTemplate = (String) result.getRequest().getAttribute(
|
||||
"org.springframework.restdocs.urlTemplate");
|
||||
Assert.notNull(urlTemplate,
|
||||
"urlTemplate not found. Did you use RestDocumentationRequestBuilders to "
|
||||
+ "build the request?");
|
||||
return urlTemplate;
|
||||
}
|
||||
|
||||
private static String getParameterName(String match) {
|
||||
int colonIdx = match.indexOf(':');
|
||||
return (colonIdx != -1 ? match.substring(0, colonIdx) : match);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void verificationFailed(Set<String> undocumentedParameters,
|
||||
Set<String> missingParameters) {
|
||||
String message = "";
|
||||
if (!undocumentedParameters.isEmpty()) {
|
||||
message += "Path parameters with the following names were not documented: "
|
||||
+ undocumentedParameters;
|
||||
}
|
||||
if (!missingParameters.isEmpty()) {
|
||||
if (message.length() > 0) {
|
||||
message += ". ";
|
||||
}
|
||||
message += "Path parameters with the following names were not found in "
|
||||
+ "the request: " + missingParameters;
|
||||
}
|
||||
throw new SnippetGenerationException(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,20 +16,12 @@
|
||||
|
||||
package org.springframework.restdocs.request;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.restdocs.snippet.SnippetGenerationException;
|
||||
import org.springframework.restdocs.snippet.SnippetWritingResultHandler;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link SnippetWritingResultHandler} that produces a snippet documenting the query
|
||||
@@ -37,60 +29,35 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class QueryParametersSnippetResultHandler extends SnippetWritingResultHandler {
|
||||
|
||||
private final Map<String, ParameterDescriptor> descriptorsByName = new LinkedHashMap<>();
|
||||
public class QueryParametersSnippetResultHandler extends
|
||||
AbstractParametersSnippetResultHandler {
|
||||
|
||||
protected QueryParametersSnippetResultHandler(String identifier,
|
||||
Map<String, Object> attributes, ParameterDescriptor... descriptors) {
|
||||
super(identifier, "query-parameters", attributes);
|
||||
for (ParameterDescriptor descriptor : descriptors) {
|
||||
Assert.hasText(descriptor.getName());
|
||||
Assert.hasText(descriptor.getDescription());
|
||||
this.descriptorsByName.put(descriptor.getName(), descriptor);
|
||||
}
|
||||
super(identifier, "query-parameters", attributes, descriptors);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> doHandle(MvcResult result) throws IOException {
|
||||
verifyParameterDescriptors(result);
|
||||
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
List<Map<String, Object>> parameters = new ArrayList<>();
|
||||
for (Entry<String, ParameterDescriptor> entry : this.descriptorsByName.entrySet()) {
|
||||
parameters.add(entry.getValue().toModel());
|
||||
protected void verificationFailed(Set<String> undocumentedParameters,
|
||||
Set<String> missingParameters) {
|
||||
String message = "";
|
||||
if (!undocumentedParameters.isEmpty()) {
|
||||
message += "Query parameters with the following names were not documented: "
|
||||
+ undocumentedParameters;
|
||||
}
|
||||
model.put("parameters", parameters);
|
||||
return model;
|
||||
if (!missingParameters.isEmpty()) {
|
||||
if (message.length() > 0) {
|
||||
message += ". ";
|
||||
}
|
||||
message += "Query parameters with the following names were not found in the request: "
|
||||
+ missingParameters;
|
||||
}
|
||||
throw new SnippetGenerationException(message);
|
||||
}
|
||||
|
||||
private void verifyParameterDescriptors(MvcResult result) {
|
||||
Set<String> actualParameters = result.getRequest().getParameterMap().keySet();
|
||||
Set<String> expectedParameters = this.descriptorsByName.keySet();
|
||||
|
||||
Set<String> undocumentedParameters = new HashSet<String>(actualParameters);
|
||||
undocumentedParameters.removeAll(expectedParameters);
|
||||
|
||||
Set<String> missingParameters = new HashSet<String>(expectedParameters);
|
||||
missingParameters.removeAll(actualParameters);
|
||||
|
||||
if (!undocumentedParameters.isEmpty() || !missingParameters.isEmpty()) {
|
||||
String message = "";
|
||||
if (!undocumentedParameters.isEmpty()) {
|
||||
message += "Query parameters with the following names were not documented: "
|
||||
+ undocumentedParameters;
|
||||
}
|
||||
if (!missingParameters.isEmpty()) {
|
||||
if (message.length() > 0) {
|
||||
message += ". ";
|
||||
}
|
||||
message += "Query parameters with the following names were not found in the request: "
|
||||
+ missingParameters;
|
||||
}
|
||||
throw new SnippetGenerationException(message);
|
||||
}
|
||||
|
||||
Assert.isTrue(actualParameters.equals(expectedParameters));
|
||||
@Override
|
||||
protected Set<String> extractActualParameters(MvcResult result) {
|
||||
return result.getRequest().getParameterMap().keySet();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,6 +32,22 @@ public abstract class RequestDocumentation {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SnippetWritingResultHandler} that will produce a snippet
|
||||
* documenting a request's path parameters.
|
||||
*
|
||||
* @param identifier An identifier for the API call that is being documented
|
||||
* @param attributes Attributes made available during rendering of the path parameters
|
||||
* snippet
|
||||
* @param descriptors The descriptions of the parameters in the request's path
|
||||
* @return the result handler
|
||||
* @see RestDocumentationResultHandler#withPathParameters(ParameterDescriptor...)
|
||||
*/
|
||||
public static SnippetWritingResultHandler documentPathParameters(String identifier,
|
||||
Map<String, Object> attributes, ParameterDescriptor... descriptors) {
|
||||
return new PathParametersSnippetResultHandler(identifier, attributes, descriptors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SnippetWritingResultHandler} that will produce a snippet
|
||||
* documenting a request's query parameters
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
|===
|
||||
|Parameter|Description
|
||||
|
||||
{{#parameters}}
|
||||
|{{name}}
|
||||
|{{description}}
|
||||
|
||||
{{/parameters}}
|
||||
|===
|
||||
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.restdocs.RestDocumentation.document;
|
||||
import static org.springframework.restdocs.RestDocumentation.modifyResponseTo;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
|
||||
import static org.springframework.restdocs.response.ResponsePostProcessors.maskLinks;
|
||||
import static org.springframework.restdocs.response.ResponsePostProcessors.prettyPrintContent;
|
||||
import static org.springframework.restdocs.response.ResponsePostProcessors.removeHeaders;
|
||||
@@ -30,7 +31,6 @@ import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.httpResponse;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.snippet;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.delete;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.fileUpload;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.head;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.options;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.patch;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.put;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.request;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
/**
|
||||
* Tests for {@link RestDocumentationRequestBuilders}
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*
|
||||
*/
|
||||
public class RestDocumentationRequestBuildersTests {
|
||||
|
||||
private final ServletContext servletContext = new MockServletContext();
|
||||
|
||||
@Test
|
||||
public void getTemplate() {
|
||||
assertTemplate(get("{template}", "t"), HttpMethod.GET);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUri() {
|
||||
assertUri(get(URI.create("/uri")), HttpMethod.GET);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postTemplate() {
|
||||
assertTemplate(post("{template}", "t"), HttpMethod.POST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postUri() {
|
||||
assertUri(post(URI.create("/uri")), HttpMethod.POST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putTemplate() {
|
||||
assertTemplate(put("{template}", "t"), HttpMethod.PUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putUri() {
|
||||
assertUri(put(URI.create("/uri")), HttpMethod.PUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchTemplate() {
|
||||
assertTemplate(patch("{template}", "t"), HttpMethod.PATCH);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchUri() {
|
||||
assertUri(patch(URI.create("/uri")), HttpMethod.PATCH);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteTemplate() {
|
||||
assertTemplate(delete("{template}", "t"), HttpMethod.DELETE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteUri() {
|
||||
assertUri(delete(URI.create("/uri")), HttpMethod.DELETE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void optionsTemplate() {
|
||||
assertTemplate(options("{template}", "t"), HttpMethod.OPTIONS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void optionsUri() {
|
||||
assertUri(options(URI.create("/uri")), HttpMethod.OPTIONS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headTemplate() {
|
||||
assertTemplate(head("{template}", "t"), HttpMethod.HEAD);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headUri() {
|
||||
assertUri(head(URI.create("/uri")), HttpMethod.HEAD);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestTemplate() {
|
||||
assertTemplate(request(HttpMethod.GET, "{template}", "t"), HttpMethod.GET);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUri() {
|
||||
assertUri(request(HttpMethod.GET, URI.create("/uri")), HttpMethod.GET);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileUploadTemplate() {
|
||||
assertTemplate(fileUpload("{template}", "t"), HttpMethod.POST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileUploadUri() {
|
||||
assertUri(fileUpload(URI.create("/uri")), HttpMethod.POST);
|
||||
}
|
||||
|
||||
private void assertTemplate(MockHttpServletRequestBuilder builder,
|
||||
HttpMethod httpMethod) {
|
||||
MockHttpServletRequest request = builder.buildRequest(this.servletContext);
|
||||
assertThat(
|
||||
(String) request.getAttribute("org.springframework.restdocs.urlTemplate"),
|
||||
is(equalTo("{template}")));
|
||||
assertThat(request.getRequestURI(), is(equalTo("t")));
|
||||
assertThat(request.getMethod(), is(equalTo(httpMethod.name())));
|
||||
}
|
||||
|
||||
private void assertUri(MockHttpServletRequestBuilder builder, HttpMethod httpMethod) {
|
||||
MockHttpServletRequest request = builder.buildRequest(this.servletContext);
|
||||
assertThat(request.getRequestURI(), is(equalTo("/uri")));
|
||||
assertThat(request.getMethod(), is(equalTo(httpMethod.name())));
|
||||
}
|
||||
}
|
||||
@@ -19,15 +19,15 @@ package org.springframework.restdocs.curl;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.fileUpload;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.put;
|
||||
import static org.springframework.restdocs.curl.CurlDocumentation.documentCurlRequest;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.codeBlock;
|
||||
import static org.springframework.restdocs.test.StubMvcResult.result;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.fileUpload;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -45,7 +45,7 @@ import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
|
||||
/**
|
||||
* Tests for {@link CurlDocumentation}
|
||||
*
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Yann Le Guern
|
||||
* @author Dmitriy Mayboroda
|
||||
|
||||
@@ -21,6 +21,10 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.fileUpload;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.put;
|
||||
import static org.springframework.restdocs.http.HttpDocumentation.documentHttpRequest;
|
||||
import static org.springframework.restdocs.http.HttpDocumentation.documentHttpResponse;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
@@ -28,10 +32,6 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.httpRequest;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.httpResponse;
|
||||
import static org.springframework.restdocs.test.StubMvcResult.result;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.fileUpload;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.GET;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.POST;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.PUT;
|
||||
@@ -53,7 +53,7 @@ import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
|
||||
/**
|
||||
* Tests for {@link HttpDocumentation}
|
||||
*
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Jonathan Pearlin
|
||||
*/
|
||||
|
||||
@@ -20,6 +20,7 @@ import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.startsWith;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.documentRequestFields;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.documentResponseFields;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
@@ -27,7 +28,6 @@ import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.tableWithHeader;
|
||||
import static org.springframework.restdocs.test.StubMvcResult.result;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -45,7 +45,7 @@ import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
|
||||
/**
|
||||
* Tests for {@link PayloadDocumentation}
|
||||
*
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class PayloadDocumentationTests {
|
||||
|
||||
@@ -20,13 +20,14 @@ import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.startsWith;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.documentPathParameters;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.documentQueryParameters;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
import static org.springframework.restdocs.test.RestDocumentationRequestBuilders.get;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.tableWithHeader;
|
||||
import static org.springframework.restdocs.test.StubMvcResult.result;
|
||||
import static org.springframework.restdocs.test.TestRequestBuilders.get;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -56,56 +57,56 @@ public class RequestDocumentationTests {
|
||||
public ExpectedSnippet snippet = new ExpectedSnippet();
|
||||
|
||||
@Test
|
||||
public void undocumentedParameter() throws IOException {
|
||||
public void undocumentedQueryParameter() throws IOException {
|
||||
this.thrown.expect(SnippetGenerationException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Query parameters with the following names were"
|
||||
+ " not documented: [a]"));
|
||||
documentQueryParameters("undocumented-parameter", null).handle(
|
||||
documentQueryParameters("undocumented-query-parameter", null).handle(
|
||||
result(get("/").param("a", "alpha")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingParameter() throws IOException {
|
||||
public void missingQueryParameter() throws IOException {
|
||||
this.thrown.expect(SnippetGenerationException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Query parameters with the following names were"
|
||||
+ " not found in the request: [a]"));
|
||||
documentQueryParameters("missing-parameter", null,
|
||||
documentQueryParameters("missing-query-parameter", null,
|
||||
parameterWithName("a").description("one")).handle(result(get("/")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedParameterAndMissingParameter() throws IOException {
|
||||
public void undocumentedAndMissingQueryParameters() throws IOException {
|
||||
this.thrown.expect(SnippetGenerationException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Query parameters with the following names were"
|
||||
+ " not documented: [b]. Query parameters with the following"
|
||||
+ " names were not found in the request: [a]"));
|
||||
documentQueryParameters("undocumented-parameter-missing-parameter", null,
|
||||
documentQueryParameters("undocumented-and-missing-query-parameters", null,
|
||||
parameterWithName("a").description("one")).handle(
|
||||
result(get("/").param("b", "bravo")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterSnippetFromRequestParameters() throws IOException {
|
||||
this.snippet.expectQueryParameters("parameter-snippet-request-parameters")
|
||||
public void queryParameterSnippetFromRequestParameters() throws IOException {
|
||||
this.snippet.expectQueryParameters("query-parameter-snippet-request-parameters")
|
||||
.withContents(
|
||||
tableWithHeader("Parameter", "Description").row("a", "one").row(
|
||||
"b", "two"));
|
||||
documentQueryParameters("parameter-snippet-request-parameters", null,
|
||||
documentQueryParameters("query-parameter-snippet-request-parameters", null,
|
||||
parameterWithName("a").description("one"),
|
||||
parameterWithName("b").description("two")).handle(
|
||||
result(get("/").param("a", "bravo").param("b", "bravo")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterSnippetFromRequestUriQueryString() throws IOException {
|
||||
this.snippet.expectQueryParameters("parameter-snippet-request-uri-query-string")
|
||||
.withContents(
|
||||
tableWithHeader("Parameter", "Description").row("a", "one").row(
|
||||
"b", "two"));
|
||||
documentQueryParameters("parameter-snippet-request-uri-query-string", null,
|
||||
public void queryParameterSnippetFromRequestUriQueryString() throws IOException {
|
||||
this.snippet.expectQueryParameters(
|
||||
"query-parameter-snippet-request-uri-query-string").withContents(
|
||||
tableWithHeader("Parameter", "Description").row("a", "one").row("b",
|
||||
"two"));
|
||||
documentQueryParameters("query-parameter-snippet-request-uri-query-string", null,
|
||||
parameterWithName("a").description("one"),
|
||||
parameterWithName("b").description("two")).handle(
|
||||
result(get("/?a=alpha&b=bravo").requestAttr(
|
||||
@@ -114,12 +115,11 @@ public class RequestDocumentationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parametersWithCustomDescriptorAttributes() throws IOException {
|
||||
this.snippet
|
||||
.expectQueryParameters("parameters-with-custom-descriptor-attributes")
|
||||
.withContents(
|
||||
tableWithHeader("Parameter", "Description", "Foo").row("a",
|
||||
"one", "alpha").row("b", "two", "bravo"));
|
||||
public void queryParametersWithCustomDescriptorAttributes() throws IOException {
|
||||
this.snippet.expectQueryParameters(
|
||||
"query-parameters-with-custom-descriptor-attributes").withContents(
|
||||
tableWithHeader("Parameter", "Description", "Foo").row("a", "one",
|
||||
"alpha").row("b", "two", "bravo"));
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
when(resolver.resolveTemplateResource("query-parameters"))
|
||||
.thenReturn(
|
||||
@@ -131,7 +131,7 @@ public class RequestDocumentationTests {
|
||||
request.addParameter("a", "bravo");
|
||||
request.addParameter("b", "bravo");
|
||||
documentQueryParameters(
|
||||
"parameters-with-custom-descriptor-attributes",
|
||||
"query-parameters-with-custom-descriptor-attributes",
|
||||
null,
|
||||
parameterWithName("a").description("one").attributes(
|
||||
key("foo").value("alpha")),
|
||||
@@ -140,8 +140,8 @@ public class RequestDocumentationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parametersWithCustomAttributes() throws IOException {
|
||||
this.snippet.expectQueryParameters("parameters-with-custom-attributes")
|
||||
public void queryParametersWithCustomAttributes() throws IOException {
|
||||
this.snippet.expectQueryParameters("query-parameters-with-custom-attributes")
|
||||
.withContents(startsWith(".The title"));
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
when(resolver.resolveTemplateResource("query-parameters"))
|
||||
@@ -154,7 +154,7 @@ public class RequestDocumentationTests {
|
||||
request.addParameter("a", "bravo");
|
||||
request.addParameter("b", "bravo");
|
||||
documentQueryParameters(
|
||||
"parameters-with-custom-attributes",
|
||||
"query-parameters-with-custom-attributes",
|
||||
attributes(key("title").value("The title")),
|
||||
parameterWithName("a").description("one").attributes(
|
||||
key("foo").value("alpha")),
|
||||
@@ -162,4 +162,91 @@ public class RequestDocumentationTests {
|
||||
key("foo").value("bravo"))).handle(result(request));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedPathParameter() throws IOException {
|
||||
this.thrown.expect(SnippetGenerationException.class);
|
||||
this.thrown.expectMessage(equalTo("Path parameters with the following names were"
|
||||
+ " not documented: [a]"));
|
||||
documentPathParameters("undocumented-path-parameter", null).handle(
|
||||
result(get("/{a}/", "alpha")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingPathParameter() throws IOException {
|
||||
this.thrown.expect(SnippetGenerationException.class);
|
||||
this.thrown.expectMessage(equalTo("Path parameters with the following names were"
|
||||
+ " not found in the request: [a]"));
|
||||
documentPathParameters("missing-path-parameter", null,
|
||||
parameterWithName("a").description("one")).handle(result(get("/")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedAndMissingPathParameters() throws IOException {
|
||||
this.thrown.expect(SnippetGenerationException.class);
|
||||
this.thrown.expectMessage(equalTo("Path parameters with the following names were"
|
||||
+ " not documented: [b]. Path parameters with the following"
|
||||
+ " names were not found in the request: [a]"));
|
||||
documentPathParameters("undocumented-and-missing-path-parameters", null,
|
||||
parameterWithName("a").description("one")).handle(
|
||||
result(get("/{b}", "bravo")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathParameters() throws IOException {
|
||||
this.snippet.expectPathParameters("path-parameters").withContents(
|
||||
tableWithHeader("Parameter", "Description").row("a", "one").row("b",
|
||||
"two"));
|
||||
documentPathParameters("path-parameters", null,
|
||||
parameterWithName("a").description("one"),
|
||||
parameterWithName("b").description("two")).handle(
|
||||
result(get("/{a}/{b}", "alpha", "banana").requestAttr(
|
||||
RestDocumentationContext.class.getName(),
|
||||
new RestDocumentationContext())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathParametersWithCustomDescriptorAttributes() throws IOException {
|
||||
this.snippet.expectPathParameters(
|
||||
"path-parameters-with-custom-descriptor-attributes").withContents(
|
||||
tableWithHeader("Parameter", "Description", "Foo").row("a", "one",
|
||||
"alpha").row("b", "two", "bravo"));
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
when(resolver.resolveTemplateResource("path-parameters"))
|
||||
.thenReturn(
|
||||
new FileSystemResource(
|
||||
"src/test/resources/custom-snippet-templates/path-parameters-with-extra-column.snippet"));
|
||||
documentPathParameters(
|
||||
"path-parameters-with-custom-descriptor-attributes",
|
||||
null,
|
||||
parameterWithName("a").description("one").attributes(
|
||||
key("foo").value("alpha")),
|
||||
parameterWithName("b").description("two").attributes(
|
||||
key("foo").value("bravo"))).handle(
|
||||
result(get("{a}/{b}", "alpha", "bravo").requestAttr(
|
||||
TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathParametersWithCustomAttributes() throws IOException {
|
||||
this.snippet.expectPathParameters("path-parameters-with-custom-attributes")
|
||||
.withContents(startsWith(".The title"));
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
when(resolver.resolveTemplateResource("path-parameters"))
|
||||
.thenReturn(
|
||||
new FileSystemResource(
|
||||
"src/test/resources/custom-snippet-templates/path-parameters-with-title.snippet"));
|
||||
documentPathParameters(
|
||||
"path-parameters-with-custom-attributes",
|
||||
attributes(key("title").value("The title")),
|
||||
parameterWithName("a").description("one").attributes(
|
||||
key("foo").value("alpha")),
|
||||
parameterWithName("b").description("two").attributes(
|
||||
key("foo").value("bravo"))).handle(
|
||||
result(get("{a}/{b}", "alpha", "bravo").requestAttr(
|
||||
TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver))));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,6 +135,11 @@ public class ExpectedSnippet implements TestRule {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpectedSnippet expectPathParameters(String name) {
|
||||
expect(name, "path-parameters");
|
||||
return this;
|
||||
}
|
||||
|
||||
private ExpectedSnippet expect(String name, String type) {
|
||||
this.expectedName = name;
|
||||
this.expectedType = type;
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
package org.springframework.restdocs.test;
|
||||
|
||||
import org.springframework.restdocs.config.RestDocumentationContext;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
public class RestDocumentationRequestBuilders {
|
||||
|
||||
private RestDocumentationRequestBuilders() {
|
||||
|
||||
}
|
||||
|
||||
public static MockHttpServletRequestBuilder get(String urlTemplate) {
|
||||
return MockMvcRequestBuilders.get(urlTemplate).requestAttr(
|
||||
RestDocumentationContext.class.getName(), new RestDocumentationContext());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.test;
|
||||
|
||||
import org.springframework.restdocs.config.RestDocumentationContext;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
public class TestRequestBuilders {
|
||||
|
||||
private TestRequestBuilders() {
|
||||
|
||||
}
|
||||
|
||||
public static MockHttpServletRequestBuilder get(String urlTemplate,
|
||||
Object... urlVariables) {
|
||||
return org.springframework.restdocs.RestDocumentationRequestBuilders.get(
|
||||
urlTemplate, urlVariables).requestAttr(
|
||||
RestDocumentationContext.class.getName(), new RestDocumentationContext());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
|===
|
||||
|Parameter|Description|Foo
|
||||
|
||||
{{#parameters}}
|
||||
|{{name}}
|
||||
|{{description}}
|
||||
|{{foo}}
|
||||
|
||||
{{/parameters}}
|
||||
|===
|
||||
@@ -0,0 +1,10 @@
|
||||
.{{title}}
|
||||
|===
|
||||
|Parameter|Description
|
||||
|
||||
{{#parameters}}
|
||||
|{{name}}
|
||||
|{{description}}
|
||||
|
||||
{{/parameters}}
|
||||
|===
|
||||
Reference in New Issue
Block a user