Add support for using REST Assured to generate documentation snippets
This commit adds a new module, spring-restdocs-restassured, that can be used to generate documentation snippets when testing a service with REST Assured. Please refer to the updated reference documentation for details. Thanks to Johan Haleby for making a change to REST Assured so that path parameters could be documented. Closes gh-102
This commit is contained in:
@@ -58,6 +58,7 @@ subprojects {
|
||||
}
|
||||
dependencies {
|
||||
dependency 'com.fasterxml.jackson.core:jackson-databind:2.4.6.1'
|
||||
dependency 'com.jayway.restassured:rest-assured:2.8.0'
|
||||
dependency 'com.samskivert:jmustache:1.11'
|
||||
dependency 'commons-codec:commons-codec:1.10'
|
||||
dependency 'javax.servlet:javax.servlet-api:3.1.0'
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
<module name="AvoidStarImport" />
|
||||
<module name="AvoidStaticImport">
|
||||
<property name="excludes"
|
||||
value="org.junit.Assert.*, org.junit.Assume.*, org.hamcrest.CoreMatchers.*, org.hamcrest.Matchers.*, org.mockito.Mockito.*, org.mockito.BDDMockito.*, org.mockito.Matchers.*, org.springframework.restdocs.curl.CurlDocumentation.*, org.springframework.restdocs.headers.HeaderDocumentation.*, org.springframework.restdocs.hypermedia.HypermediaDocumentation.*, org.springframework.restdocs.mockmvc.IterableEnumeration.*, org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.*, org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*, org.springframework.restdocs.payload.PayloadDocumentation.*, org.springframework.restdocs.operation.preprocess.Preprocessors.*, org.springframework.restdocs.request.RequestDocumentation.*, org.springframework.restdocs.snippet.Attributes.*, org.springframework.restdocs.test.SnippetMatchers.*, org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*, org.springframework.test.web.servlet.result.MockMvcResultMatchers.*" />
|
||||
value="com.jayway.restassured.RestAssured.*, org.junit.Assert.*, org.junit.Assume.*, org.hamcrest.CoreMatchers.*, org.hamcrest.Matchers.*, org.mockito.Mockito.*, org.mockito.BDDMockito.*, org.mockito.Matchers.*, org.springframework.restdocs.curl.CurlDocumentation.*, org.springframework.restdocs.headers.HeaderDocumentation.*, org.springframework.restdocs.hypermedia.HypermediaDocumentation.*, org.springframework.restdocs.mockmvc.IterableEnumeration.*, org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.*, org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*, org.springframework.restdocs.payload.PayloadDocumentation.*, org.springframework.restdocs.operation.preprocess.Preprocessors.*, org.springframework.restdocs.request.RequestDocumentation.*, org.springframework.restdocs.restassured.RestAssuredRestDocumentation.*, org.springframework.restdocs.restassured.operation.preprocess.RestAssuredPreprocessors.*, org.springframework.restdocs.snippet.Attributes.*, org.springframework.restdocs.test.SnippetMatchers.*, org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*, org.springframework.test.web.servlet.result.MockMvcResultMatchers.*" />
|
||||
</module>
|
||||
<module name="IllegalImport" />
|
||||
<module name="RedundantImport" />
|
||||
|
||||
@@ -4,6 +4,7 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
testCompile project(':spring-restdocs-mockmvc')
|
||||
testCompile project(':spring-restdocs-restassured')
|
||||
testCompile 'javax.validation:validation-api'
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,12 @@
|
||||
[[configuration-uris]]
|
||||
=== Documented URIs
|
||||
|
||||
The default configuration for URIs documented by Spring REST Docs is:
|
||||
NOTE: As REST Assured tests a service by making actual HTTP requests, the documented
|
||||
URIs cannot be customized in this way. You should use the
|
||||
<<customizing-requests-and-responses-preprocessors-modify-uris, REST-Assured specific
|
||||
preprocessor>> instead.
|
||||
|
||||
When using MockMvc, the default configuration for URIs documented by Spring REST Docs is:
|
||||
|
||||
|===
|
||||
|Setting |Default
|
||||
@@ -21,12 +26,12 @@ The default configuration for URIs documented by Spring REST Docs is:
|
||||
|`8080`
|
||||
|===
|
||||
|
||||
This configuration is applied by `RestDocumentationMockMvcConfigurer`. You can use its API
|
||||
This configuration is applied by `MockMvcRestDocumentationConfigurer`. You can use its API
|
||||
to change one or more of the defaults to suit your needs:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::{examples-dir}/com/example/CustomUriConfiguration.java[tags=custom-uri-configuration]
|
||||
include::{examples-dir}/com/example/mockmvc/CustomUriConfiguration.java[tags=custom-uri-configuration]
|
||||
----
|
||||
|
||||
TIP: To configure a request's context path, use the `contextPath` method on
|
||||
@@ -38,12 +43,19 @@ TIP: To configure a request's context path, use the `contextPath` method on
|
||||
=== Snippet encoding
|
||||
|
||||
The default encoding used by Asciidoctor is `UTF-8`. Spring REST Docs adopts the same
|
||||
default for the snippets that it generates. If you require an encoding other than `UTF-8`,
|
||||
use `RestDocumentationMockMvcConfigurer` to configure it:
|
||||
default for the snippets that it generates. You can change the default snippet encoding
|
||||
using the `RestDocumentationConfigurer` API. For example, to use `ISO-8859-1`:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/CustomEncoding.java[tags=custom-encoding]
|
||||
include::{examples-dir}/com/example/mockmvc/CustomEncoding.java[tags=custom-encoding]
|
||||
----
|
||||
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/CustomEncoding.java[tags=custom-encoding]
|
||||
----
|
||||
|
||||
|
||||
@@ -57,11 +69,18 @@ Three snippets are produced by default:
|
||||
- `http-request`
|
||||
- `http-response`
|
||||
|
||||
This default configuration is applied by `RestDocumentationMockMvcConfigurer`. You can use
|
||||
its API to change the configuration. For example, to only produce the `curl-request`
|
||||
You can change the default snippet configuration during setup using the
|
||||
`RestDocumentationConfigurer` API. For example, to only produce the `curl-request`
|
||||
snippet by default:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/CustomDefaultSnippetsConfiguration.java[tags=custom-default-snippets]
|
||||
include::{examples-dir}/com/example/mockmvc/CustomDefaultSnippets.java[tags=custom-default-snippets]
|
||||
----
|
||||
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/CustomDefaultSnippets.java[tags=custom-default-snippets]
|
||||
----
|
||||
@@ -10,9 +10,18 @@ and/or an `OperationResponsePreprocessor`. Instances can be obtained using the
|
||||
static `preprocessRequest` and `preprocessResponse` methods on `Preprocessors`. For
|
||||
example:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/PerTestPreprocessing.java[tags=preprocessing]
|
||||
include::{examples-dir}/com/example/mockmvc/PerTestPreprocessing.java[tags=preprocessing]
|
||||
----
|
||||
<1> Apply a request preprocessor that will remove the header named `Foo`.
|
||||
<2> Apply a response preprocessor that will pretty print its content.
|
||||
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/PerTestPreprocessing.java[tags=preprocessing]
|
||||
----
|
||||
<1> Apply a request preprocessor that will remove the header named `Foo`.
|
||||
<2> Apply a response preprocessor that will pretty print its content.
|
||||
@@ -22,25 +31,44 @@ so by configuring the preprocessors in your `@Before` method and using the
|
||||
<<documentating-your-api-parameterized-output-directories, support for parameterized
|
||||
output directories>>:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/EveryTestPreprocessing.java[tags=setup]
|
||||
include::{examples-dir}/com/example/mockmvc/EveryTestPreprocessing.java[tags=setup]
|
||||
----
|
||||
<1> Create the `RestDocumentationResultHandler`, configured to preprocess the request
|
||||
<1> Create a `RestDocumentationResultHandler`, configured to preprocess the request
|
||||
and response.
|
||||
<2> Create the `MockMvc` instance, configured to always call the documentation result
|
||||
<2> Create a `MockMvc` instance, configured to always call the documentation result
|
||||
handler.
|
||||
|
||||
Then, in each test, the `RestDocumentationResultHandler` can be configured with anything
|
||||
test-specific. For example:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/EveryTestPreprocessing.java[tags=use]
|
||||
include::{examples-dir}/com/example/restassured/EveryTestPreprocessing.java[tags=setup]
|
||||
----
|
||||
<1> Create a `RestDocumentationFilter`, configured to preprocess the request
|
||||
and response.
|
||||
<2> Create a `RequestSpecification` instance, configured to always call the documentation
|
||||
filter.
|
||||
|
||||
Then, in each test, any configuration specific to that test can be performed. For example:
|
||||
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/mockmvc/EveryTestPreprocessing.java[tags=use]
|
||||
----
|
||||
<1> Document the links specific to the resource that is being tested
|
||||
<2> The `perform` call will automatically produce the documentation snippets due to the
|
||||
use of `alwaysDo` above.
|
||||
<2> The request and response will be preprocessed due to the use of `alwaysDo` above.
|
||||
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/EveryTestPreprocessing.java[tags=use]
|
||||
----
|
||||
<1> Document the links specific to the resource that is being tested
|
||||
<2> The request and response will be preprocessed due to the configuration of the
|
||||
`RequestSpecification` in the `setUp` method.
|
||||
|
||||
Various built in preprocessors, including those illustrated above, are available via the
|
||||
static methods on `Preprocessors`. See <<Preprocessors, below>> for further details.
|
||||
@@ -86,6 +114,20 @@ from the request or response.
|
||||
replacing content in a request or response. Any occurrences of a regular expression are
|
||||
replaced.
|
||||
|
||||
|
||||
|
||||
[[customizing-requests-and-responses-preprocessors-modify-uris]]
|
||||
==== Modifying URIs
|
||||
|
||||
TIP: If you are using MockMvc, URIs should be customized by <<configuration-uris, changing
|
||||
the configuration>>.
|
||||
|
||||
`modifyUris` on `RestAssuredPreprocessors` can be used to modify any URIs in a request
|
||||
or a response. When using REST Assured, this allows you to customize the URIs that appear
|
||||
in the documentation while testing a local instance of the service.
|
||||
|
||||
|
||||
|
||||
[[customizing-requests-and-responses-preprocessors-writing-your-own]]
|
||||
==== Writing your own preprocessor
|
||||
|
||||
|
||||
@@ -11,9 +11,22 @@ This section provides more details about using Spring REST Docs to document your
|
||||
Spring REST Docs provides support for documenting the links in a
|
||||
https://en.wikipedia.org/wiki/HATEOAS[Hypermedia-based] API:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/Hypermedia.java[tag=links]
|
||||
include::{examples-dir}/com/example/mockmvc/Hypermedia.java[tag=links]
|
||||
----
|
||||
<1> Configure Spring REST docs to produce a snippet describing the response's links.
|
||||
Uses the static `links` method on
|
||||
`org.springframework.restdocs.hypermedia.HypermediaDocumentation`.
|
||||
<2> Expect a link whose rel is `alpha`. Uses the static `linkWithRel` method on
|
||||
`org.springframework.restdocs.hypermedia.HypermediaDocumentation`.
|
||||
<3> Expect a link whose rel is `bravo`.
|
||||
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/Hypermedia.java[tag=links]
|
||||
----
|
||||
<1> Configure Spring REST docs to produce a snippet describing the response's links.
|
||||
Uses the static `links` method on
|
||||
@@ -47,14 +60,23 @@ Two link formats are understood by default:
|
||||
If you are using Atom or HAL-format links but with a different content type you can
|
||||
provide one of the built-in `LinkExtractor` implementations to `links`. For example:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/Hypermedia.java[tag=explicit-extractor]
|
||||
include::{examples-dir}/com/example/mockmvc/Hypermedia.java[tag=explicit-extractor]
|
||||
----
|
||||
<1> Indicate that the links are in HAL format. Uses the static `halLinks` method on
|
||||
`org.springframework.restdocs.hypermedia.HypermediaDocumentation`.
|
||||
|
||||
If your API represents its links in a format other than Atom or HAL you can provide your
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/Hypermedia.java[tag=explicit-extractor]
|
||||
----
|
||||
<1> Indicate that the links are in HAL format. Uses the static `halLinks` method on
|
||||
`org.springframework.restdocs.hypermedia.HypermediaDocumentation`.
|
||||
|
||||
If your API represents its links in a format other than Atom or HAL, you can provide your
|
||||
own implementation of the `LinkExtractor` interface to extract the links from the
|
||||
response.
|
||||
|
||||
@@ -65,9 +87,22 @@ In addition to the hypermedia-specific support <<documenting-your-api-hypermedia
|
||||
above>>, support for general documentation of request and response payloads is also
|
||||
provided. For example:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/Payload.java[tags=response]
|
||||
include::{examples-dir}/com/example/mockmvc/Payload.java[tags=response]
|
||||
----
|
||||
<1> Configure Spring REST docs to produce a snippet describing the fields in the response
|
||||
payload. To document a request `requestFields` can be used. Both are static methods on
|
||||
`org.springframework.restdocs.payload.PayloadDocumentation`.
|
||||
<2> Expect a field with the path `contact`. Uses the static `fieldWithPath` method on
|
||||
`org.springframework.restdocs.payload.PayloadDocumentation`.
|
||||
<3> Expect a field with the path `contact.email`.
|
||||
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/Payload.java[tags=response]
|
||||
----
|
||||
<1> Configure Spring REST docs to produce a snippet describing the fields in the response
|
||||
payload. To document a request `requestFields` can be used. Both are static methods on
|
||||
@@ -223,9 +258,17 @@ The type can also be set explicitly using the `type(Object)` method on
|
||||
in the documentation. Typically, one of the values enumerated by `JsonFieldType` will be
|
||||
used:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/Payload.java[tags=explicit-type]
|
||||
include::{examples-dir}/com/example/mockmvc/Payload.java[tags=explicit-type]
|
||||
----
|
||||
<1> Set the field's type to `string`.
|
||||
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/Payload.java[tags=explicit-type]
|
||||
----
|
||||
<1> Set the field's type to `string`.
|
||||
|
||||
@@ -255,9 +298,10 @@ method will be used in the documentation.
|
||||
A request's parameters can be documented using `requestParameters`. Request parameters
|
||||
can be included in a `GET` request's query string. For example:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/RequestParameters.java[tags=request-parameters-query-string]
|
||||
include::{examples-dir}/com/example/mockmvc/RequestParameters.java[tags=request-parameters-query-string]
|
||||
----
|
||||
<1> Perform a `GET` request with two parameters, `page` and `per_page` in the query
|
||||
string.
|
||||
@@ -268,14 +312,37 @@ include::{examples-dir}/com/example/RequestParameters.java[tags=request-paramete
|
||||
`org.springframework.restdocs.request.RequestDocumentation`.
|
||||
<4> Document the `per_page` parameter.
|
||||
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/RequestParameters.java[tags=request-parameters-query-string]
|
||||
----
|
||||
<1> Configure Spring REST Docs to produce a snippet describing the request's parameters.
|
||||
Uses the static `requestParameters` method on
|
||||
`org.springframework.restdocs.request.RequestDocumentation`.
|
||||
<2> Document the `page` parameter. Uses the static `parameterWithName` method on
|
||||
`org.springframework.restdocs.request.RequestDocumentation`.
|
||||
<3> Document the `per_page` parameter.
|
||||
<4> Perform a `GET` request with two parameters, `page` and `per_page` in the query
|
||||
string.
|
||||
|
||||
Request parameters can also be included as form data in the body of a POST request:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/RequestParameters.java[tags=request-parameters-form-data]
|
||||
include::{examples-dir}/com/example/mockmvc/RequestParameters.java[tags=request-parameters-form-data]
|
||||
----
|
||||
<1> Perform a `POST` request with a single parameter, `username`.
|
||||
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/RequestParameters.java[tags=request-parameters-form-data]
|
||||
----
|
||||
<1> Configure the `username` parameter.
|
||||
<2> Perform the `POST` request.
|
||||
|
||||
In both cases, the result is a snippet named `request-parameters.adoc` that contains a
|
||||
table describing the parameters that are supported by the resource.
|
||||
|
||||
@@ -294,9 +361,10 @@ above.
|
||||
|
||||
A request's path parameters can be documented using `pathParameters`. For example:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/PathParameters.java[tags=path-parameters]
|
||||
include::{examples-dir}/com/example/mockmvc/PathParameters.java[tags=path-parameters]
|
||||
----
|
||||
<1> Perform a `GET` request with two path parameters, `latitude` and `longitude`.
|
||||
<2> Configure Spring REST Docs to produce a snippet describing the request's path
|
||||
@@ -306,6 +374,19 @@ include::{examples-dir}/com/example/PathParameters.java[tags=path-parameters]
|
||||
`org.springframework.restdocs.request.RequestDocumentation`.
|
||||
<4> Document the parameter named `longitude`.
|
||||
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/PathParameters.java[tags=path-parameters]
|
||||
----
|
||||
<1> Configure Spring REST Docs to produce a snippet describing the request's path
|
||||
parameters. Uses the static `pathParameters` method on
|
||||
`org.springframework.restdocs.request.RequestDocumentation`.
|
||||
<2> Document the parameter named `latitude`. Uses the static `parameterWithName` method on
|
||||
`org.springframework.restdocs.request.RequestDocumentation`.
|
||||
<3> Document the parameter named `longitude`.
|
||||
<4> Perform a `GET` request with two path parameters, `latitude` and `longitude`.
|
||||
|
||||
The result is a snippet named `path-parameters.adoc` that contains a table describing
|
||||
the path parameters that are supported by the resource.
|
||||
|
||||
@@ -329,9 +410,10 @@ above.
|
||||
The headers in a request or response can be documented using `requestHeaders` and
|
||||
`responseHeaders` respectively. For example:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/HttpHeaders.java[tags=headers]
|
||||
include::{examples-dir}/com/example/mockmvc/HttpHeaders.java[tags=headers]
|
||||
----
|
||||
<1> Perform a `GET` request with an `Authorization` header that uses basic authentication
|
||||
<2> Configure Spring REST Docs to produce a snippet describing the request's headers.
|
||||
@@ -342,6 +424,20 @@ include::{examples-dir}/com/example/HttpHeaders.java[tags=headers]
|
||||
<4> Produce a snippet describing the response's headers. Uses the static `responseHeaders`
|
||||
method on `org.springframework.restdocs.headers.HeaderDocumentation`.
|
||||
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/HttpHeaders.java[tags=headers]
|
||||
----
|
||||
<1> Configure Spring REST Docs to produce a snippet describing the request's headers.
|
||||
Uses the static `requestHeaders` method on
|
||||
`org.springframework.restdocs.headers.HeaderDocumentation`.
|
||||
<2> Document the `Authorization` header. Uses the static `headerWithName` method on
|
||||
`org.springframework.restdocs.headers.HeaderDocumentation.
|
||||
<3> Produce a snippet describing the response's headers. Uses the static `responseHeaders`
|
||||
method on `org.springframework.restdocs.headers.HeaderDocumentation`.
|
||||
<4> Configure the request with an `Authorization` header that uses basic authentication
|
||||
|
||||
The result is a snippet named `request-headers.adoc` and a snippet named
|
||||
`response-headers.adoc`. Each contains a table describing the headers.
|
||||
|
||||
@@ -436,8 +532,7 @@ class in the Spring HATEOAS-based sample illustrates the latter approach.
|
||||
[[documenting-your-api-default-snippets]]
|
||||
=== Default snippets
|
||||
|
||||
A number of snippets are produced automatically when you document a call to
|
||||
`MockMvc.perform`:
|
||||
A number of snippets are produced automatically when you document a request and response.
|
||||
|
||||
[cols="1,3"]
|
||||
|===
|
||||
@@ -489,23 +584,30 @@ are supported:
|
||||
| The nome of the test class, formatted using snake_case
|
||||
|
||||
| {step}
|
||||
| The count of calls to MockMvc.perform in the current test
|
||||
| The count of calls made to the service in the current test
|
||||
|===
|
||||
|
||||
For example, `document("{class-name}/{method-name}")` in a test method named
|
||||
`creatingANote` on the test class `GettingStartedDocumentation`, will write
|
||||
snippets into a directory named `getting-started-documentation/creating-a-note`.
|
||||
|
||||
A parameterized output directory is particularly useful in combination with Spring MVC
|
||||
Test's `alwaysDo` functionality. It allows documentation to be configured once in a setup
|
||||
method:
|
||||
A parameterized output directory is particularly useful in combination with an `@Before`
|
||||
method. It allows documentation to be configured once in a setup method and then reused
|
||||
in every test in the class:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/AlwaysDo.java[tags=always-do]
|
||||
include::{examples-dir}/com/example/mockmvc/ParameterizedOutput.java[tags=parameterized-output]
|
||||
----
|
||||
|
||||
With this configuration in place, every call to `MockMvc.perform` will produce
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/ParameterizedOutput.java[tags=parameterized-output]
|
||||
----
|
||||
|
||||
With this configuration in place, every call to the service you are testing will produce
|
||||
the <<documenting-your-api-default-snippets,default snippets>> without any further
|
||||
configuration. Take a look at the `GettingStartedDocumentation` classes in each of the
|
||||
sample applications to see this functionality in action.
|
||||
@@ -549,9 +651,19 @@ A concrete example of the above is the addition of a constraints column and a ti
|
||||
documenting request fields. The first step is to provide a `constraints` attribute for
|
||||
each field that you are documenting and to provide a `title` attribute:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/Payload.java[tags=constraints]
|
||||
include::{examples-dir}/com/example/mockmvc/Payload.java[tags=constraints]
|
||||
----
|
||||
<1> Configure the `title` attribute for the request fields snippet
|
||||
<2> Set the `constraints` attribute for the `name` field
|
||||
<3> Set the `constraints` attribute for the `email` field
|
||||
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/Payload.java[tags=constraints]
|
||||
----
|
||||
<1> Configure the `title` attribute for the request fields snippet
|
||||
<2> Set the `constraints` attribute for the `name` field
|
||||
|
||||
@@ -83,7 +83,9 @@ the configuration are described below.
|
||||
</plugins>
|
||||
</build>
|
||||
----
|
||||
<1> Add a dependency on `spring-restdocs-mockmvc` in the `test` scope.
|
||||
<1> Add a dependency on `spring-restdocs-mockmvc` in the `test` scope. If you want to use
|
||||
REST Assured rather than MockMvc, add a dependency on `spring-restdocs-restassured`
|
||||
instead.
|
||||
<2> Configure a property to define the output location for generated snippets.
|
||||
<3> Add the SureFire plugin and configure it to include files whose names end with
|
||||
`Documentation.java`.
|
||||
@@ -120,7 +122,9 @@ project's jar you should use the `prepare-package` phase.
|
||||
}
|
||||
----
|
||||
<1> Apply the Asciidoctor plugin.
|
||||
<2> Add a dependency on `spring-restdocs-mockmvc` in the `testCompile` configuration.
|
||||
<2> Add a dependency on `spring-restdocs-mockmvc` in the `testCompile` configuration. If
|
||||
you want to use REST Assured rather than MockMvc, add a dependency on
|
||||
`spring-restdocs-restassured` instead.
|
||||
<3> Configure a property to define the output location for generated snippets.
|
||||
<4> Configure the `test` task to add the snippets directory as an output.
|
||||
<5> Configure the `asciidoctor` task
|
||||
@@ -199,14 +203,16 @@ from where it will be included in the jar file.
|
||||
|
||||
[[getting-started-documentation-snippets]]
|
||||
=== Generating documentation snippets
|
||||
Spring REST Docs uses {spring-framework-docs}/#spring-mvc-test-framework[Spring's MVC Test
|
||||
framework] to make requests to the service that you are documenting. It then produces
|
||||
documentation snippets for request and resulting response.
|
||||
Spring REST Docs uses JUnit and
|
||||
{spring-framework-docs}/#spring-mvc-test-framework[Spring's MVC Test framework] or
|
||||
http://www.rest-assured.io[REST Assured] to make requests to the service that you are
|
||||
documenting. It then produces documentation snippets for the request and the resulting
|
||||
response.
|
||||
|
||||
|
||||
|
||||
[[getting-started-documentation-snippets-setup]]
|
||||
==== Setting up Spring MVC test
|
||||
==== Setting up your tests
|
||||
|
||||
The first step in generating documentation snippets is to declare a `public`
|
||||
`RestDocumentation` field that's annotated as a JUnit `@Rule`. The `RestDocumentation`
|
||||
@@ -214,47 +220,59 @@ rule is configured with the output directory into which generated snippets shoul
|
||||
written. This output directory should match the snippets directory that you have
|
||||
configured in your `build.gradle` or `pom.xml` file.
|
||||
|
||||
For Maven (`pom.xml` that will typically be `target/generated-snippets`:
|
||||
For Maven (`pom.xml` that will typically be `target/generated-snippets` and for
|
||||
Gradle (`build.gradle`) it will typically be `build/generated-snippets`:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="primary"]
|
||||
.Maven
|
||||
----
|
||||
@Rule
|
||||
public RestDocumentation restDocumentation = new RestDocumentation("target/generated-snippets");
|
||||
----
|
||||
|
||||
And for Gradle (`build.gradle`) it will typically be `build/generated-snippets`:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.Gradle
|
||||
----
|
||||
@Rule
|
||||
public RestDocumentation restDocumentation = new RestDocumentation("build/generated-snippets");
|
||||
----
|
||||
|
||||
Next, provide an `@Before` method that creates a `MockMvc` instance:
|
||||
Next, provide an `@Before` method to configure MockMvc or REST Assured:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/ExampleApplicationTests.java[tags=mock-mvc-setup]
|
||||
include::{examples-dir}/com/example/mockmvc/ExampleApplicationTests.java[tags=setup]
|
||||
----
|
||||
|
||||
The `MockMvc` instance is configured using a `RestDocumentationMockMvcConfigurer`. An
|
||||
<1> The `MockMvc` instance is configured using a `MockMvcRestDocumentationConfigurer`. An
|
||||
instance of this class can be obtained from the static `documentationConfiguration()`
|
||||
method on `org.springframework.restdocs.mockmvc.MockMvcRestDocumentation`.
|
||||
`RestDocumentationMockMvcConfigurer` applies sensible defaults and also provides an API
|
||||
for customizing the configuration. Refer to the
|
||||
<<configuration, configuration section>> for more information.
|
||||
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/ExampleApplicationTests.java[tags=setup]
|
||||
----
|
||||
<1> REST Assured is configured by adding a `RestAssuredRestDocumentationConfigurer` as a
|
||||
`Filter`. An instance of this class can be obtained from the static
|
||||
`documentationConfiguration()` method on
|
||||
`org.springframework.restdocs.restassured.RestAssuredRestDocumentation`.
|
||||
|
||||
The configurer applies sensible defaults and also provides an API for customizing the
|
||||
configuration. Refer to the <<configuration, configuration section>> for more information.
|
||||
|
||||
|
||||
|
||||
[[getting-started-documentation-snippets-invoking-the-service]]
|
||||
==== Invoking the RESTful service
|
||||
|
||||
Now that a `MockMvc` instance has been created, it can be used to invoke the RESTful
|
||||
Now that the testing framework has been configured, it can be used to invoke the RESTful
|
||||
service and document the request and response. For example:
|
||||
|
||||
[source,java,indent=0]
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/InvokeService.java[tags=invoke-service]
|
||||
include::{examples-dir}/com/example/mockmvc/InvokeService.java[tags=invoke-service]
|
||||
----
|
||||
<1> Invoke the root (`/`) of the service and indicate that an `application/json` response
|
||||
is required.
|
||||
@@ -265,6 +283,21 @@ a `RestDocumentationResultHandler`. An instance of this class can be obtained fr
|
||||
static `document` method on
|
||||
`org.springframework.restdocs.mockmvc.MockMvcRestDocumentation`.
|
||||
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/InvokeService.java[tags=invoke-service]
|
||||
----
|
||||
<1> Apply the specification that was initialised in the `@Before` method.
|
||||
<2> Indicate that an `application/json` response is required.
|
||||
<3> Document the call to the service, writing the snippets into a directory named `index`
|
||||
that will be located beneath the configured output directory. The snippets are written by
|
||||
a `RestDocumentationFilter`. An instance of this class can be obtained from the
|
||||
static `document` method on
|
||||
`org.springframework.restdocs.restassured.RestAssuredRestDocumentation`.
|
||||
<4> Invoke the root (`/`) of the service.
|
||||
<5> Assert that the service produce the expected response.
|
||||
|
||||
By default, three snippets are written:
|
||||
|
||||
* `<output-directory>/index/curl-request.adoc`
|
||||
|
||||
@@ -10,9 +10,10 @@ http://asciidoctor.org[Asciidoctor]. Asciidoctor processes plain text and produc
|
||||
HTML, styled and layed out to suit your needs.
|
||||
|
||||
Spring REST Docs makes use of snippets produced by tests written with
|
||||
{spring-framework-docs}/#spring-mvc-test-framework[Spring MVC Test]. This test-driven
|
||||
approach helps to guarantee the accuracy of your service's documentation. If a snippet is
|
||||
incorrect the test that produces it will fail.
|
||||
{spring-framework-docs}/#spring-mvc-test-framework[Spring MVC Test] or
|
||||
http://www.rest-assured.io[REST Assured]. This test-driven approach helps to guarantee the
|
||||
accuracy of your service's documentation. If a snippet is incorrect the test that produces
|
||||
it will fail.
|
||||
|
||||
Documenting a RESTful service is largely about describing its resources. Two key parts
|
||||
of each resource's description are the details of the HTTP requests that it consumes
|
||||
|
||||
@@ -41,6 +41,7 @@ public class Constraints {
|
||||
@NotNull
|
||||
@Size(min = 8)
|
||||
String password;
|
||||
|
||||
}
|
||||
// end::constraints[]
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example;
|
||||
package com.example.mockmvc;
|
||||
|
||||
import static org.springframework.restdocs.curl.CurlDocumentation.curlRequest;
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
@@ -27,7 +27,7 @@ import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
public class CustomDefaultSnippetsConfiguration {
|
||||
public class CustomDefaultSnippets {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation("build");
|
||||
@@ -41,8 +41,8 @@ public class CustomDefaultSnippetsConfiguration {
|
||||
public void setUp() {
|
||||
// tag::custom-default-snippets[]
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation).snippets()
|
||||
.withDefaults(curlRequest()))
|
||||
.apply(documentationConfiguration(this.restDocumentation)
|
||||
.snippets().withDefaults(curlRequest()))
|
||||
.build();
|
||||
// end::custom-default-snippets[]
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example;
|
||||
package com.example.mockmvc;
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
public class CustomEncoding {
|
||||
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation("build");
|
||||
|
||||
@@ -40,8 +40,8 @@ public class CustomEncoding {
|
||||
public void setUp() {
|
||||
// tag::custom-encoding[]
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation).snippets()
|
||||
.withEncoding("ISO-8859-1"))
|
||||
.apply(documentationConfiguration(this.restDocumentation)
|
||||
.snippets().withEncoding("ISO-8859-1"))
|
||||
.build();
|
||||
// end::custom-encoding[]
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example;
|
||||
package com.example.mockmvc;
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
public class CustomUriConfiguration {
|
||||
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation("build");
|
||||
|
||||
@@ -14,9 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example;
|
||||
package com.example.mockmvc;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
@@ -25,6 +27,7 @@ import org.springframework.web.context.WebApplicationContext;
|
||||
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
|
||||
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
|
||||
@@ -34,20 +37,24 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
|
||||
public class EveryTestPreprocessing {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation(
|
||||
"target/generated-snippets");
|
||||
|
||||
private WebApplicationContext context;
|
||||
|
||||
// tag::setup[]
|
||||
private MockMvc mockMvc;
|
||||
|
||||
private RestDocumentationResultHandler document;
|
||||
|
||||
// tag::setup[]
|
||||
@Before
|
||||
public void setup() {
|
||||
this.document = document(
|
||||
"{method-name}", // <1>
|
||||
this.document = document("{method-name}", // <1>
|
||||
preprocessRequest(removeHeaders("Foo")),
|
||||
preprocessResponse(prettyPrint()));
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.alwaysDo(this.document) // <2>
|
||||
.build();
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example;
|
||||
package com.example.mockmvc;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
@@ -29,8 +29,9 @@ import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.docu
|
||||
public class ExampleApplicationTests {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation("target/generated-snippets");
|
||||
// tag::mock-mvc-setup[]
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation(
|
||||
"target/generated-snippets");
|
||||
// tag::setup[]
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
@@ -39,8 +40,8 @@ public class ExampleApplicationTests {
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.apply(documentationConfiguration(this.restDocumentation)) // <1>
|
||||
.build();
|
||||
}
|
||||
// end::mock-mvc-setup[]
|
||||
// end::setup[]
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example;
|
||||
package com.example.mockmvc;
|
||||
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
@@ -32,19 +32,19 @@ public class HttpHeaders {
|
||||
public void headers() throws Exception {
|
||||
// tag::headers[]
|
||||
this.mockMvc
|
||||
.perform(get("/people").header("Authorization", "Basic dXNlcjpzZWNyZXQ=")) // <1>
|
||||
.andExpect(status().isOk())
|
||||
.andDo(document("headers",
|
||||
requestHeaders( // <2>
|
||||
headerWithName("Authorization").description(
|
||||
"Basic auth credentials")), // <3>
|
||||
responseHeaders( // <4>
|
||||
headerWithName("X-RateLimit-Limit").description(
|
||||
"The total number of requests permitted per period"),
|
||||
headerWithName("X-RateLimit-Remaining").description(
|
||||
"Remaining requests permitted in current period"),
|
||||
headerWithName("X-RateLimit-Reset").description(
|
||||
"Time at which the rate limit period will reset"))));
|
||||
.perform(get("/people").header("Authorization", "Basic dXNlcjpzZWNyZXQ=")) // <1>
|
||||
.andExpect(status().isOk())
|
||||
.andDo(document("headers",
|
||||
requestHeaders( // <2>
|
||||
headerWithName("Authorization").description(
|
||||
"Basic auth credentials")), // <3>
|
||||
responseHeaders( // <4>
|
||||
headerWithName("X-RateLimit-Limit").description(
|
||||
"The total number of requests permitted per period"),
|
||||
headerWithName("X-RateLimit-Remaining").description(
|
||||
"Remaining requests permitted in current period"),
|
||||
headerWithName("X-RateLimit-Reset").description(
|
||||
"Time at which the rate limit period will reset"))));
|
||||
// end::headers[]
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example;
|
||||
package com.example.mockmvc;
|
||||
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example;
|
||||
package com.example.mockmvc;
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
||||
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -14,10 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example;
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
package com.example.mockmvc;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
@@ -26,24 +23,25 @@ import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
public class AlwaysDo {
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
|
||||
public class ParameterizedOutput {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation("build");
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
private WebApplicationContext context;
|
||||
|
||||
|
||||
|
||||
// tag::always-do[]
|
||||
// tag::parameterized-output[]
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.alwaysDo(document("{method-name}/{step}/"))
|
||||
.build();
|
||||
.alwaysDo(document("{method-name}/{step}/")).build();
|
||||
}
|
||||
// end::always-do[]
|
||||
// end::parameterized-output[]
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example;
|
||||
package com.example.mockmvc;
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
||||
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example;
|
||||
package com.example.mockmvc;
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
||||
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
|
||||
@@ -51,7 +51,6 @@ private MockMvc mockMvc;
|
||||
.andDo(document("index", responseFields(
|
||||
fieldWithPath("contact.email")
|
||||
.type(JsonFieldType.STRING) // <1>
|
||||
.optional()
|
||||
.description("The user's email address"))));
|
||||
// end::explicit-type[]
|
||||
}
|
||||
@@ -61,16 +60,13 @@ private MockMvc mockMvc;
|
||||
.andExpect(status().isOk())
|
||||
// tag::constraints[]
|
||||
.andDo(document("create-user", requestFields(
|
||||
attributes(
|
||||
key("title").value("Fields for user creation")), // <1>
|
||||
fieldWithPath("name")
|
||||
.description("The user's name")
|
||||
.attributes(
|
||||
key("constraints").value("Must not be null. Must not be empty")), // <2>
|
||||
fieldWithPath("email")
|
||||
.description("The user's email address")
|
||||
.attributes(
|
||||
key("constraints").value("Must be a valid email address"))))); // <3>
|
||||
attributes(key("title").value("Fields for user creation")), // <1>
|
||||
fieldWithPath("name").description("The user's name")
|
||||
.attributes(key("constraints")
|
||||
.value("Must not be null. Must not be empty")), // <2>
|
||||
fieldWithPath("email").description("The user's email address")
|
||||
.attributes(key("constraints")
|
||||
.value("Must be a valid email address"))))); // <3>
|
||||
// end::constraints[]
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example;
|
||||
package com.example.mockmvc;
|
||||
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
@@ -33,8 +33,8 @@ public class PerTestPreprocessing {
|
||||
public void general() throws Exception {
|
||||
// tag::preprocessing[]
|
||||
this.mockMvc.perform(get("/")).andExpect(status().isOk())
|
||||
.andDo(document("index", preprocessRequest(removeHeaders("Foo")), // <1>
|
||||
preprocessResponse(prettyPrint()))); // <2>
|
||||
.andDo(document("index", preprocessRequest(removeHeaders("Foo")), // <1>
|
||||
preprocessResponse(prettyPrint()))); // <2>
|
||||
// end::preprocessing[]
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example;
|
||||
package com.example.mockmvc;
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
||||
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
|
||||
@@ -39,7 +39,7 @@ public class RequestParameters {
|
||||
)));
|
||||
// end::request-parameters-query-string[]
|
||||
}
|
||||
|
||||
|
||||
public void postFormDataSnippet() throws Exception {
|
||||
// tag::request-parameters-form-data[]
|
||||
this.mockMvc.perform(post("/users").param("username", "Tester")) // <1>
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
|
||||
import com.jayway.restassured.builder.RequestSpecBuilder;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
|
||||
import static org.springframework.restdocs.curl.CurlDocumentation.curlRequest;
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration;
|
||||
|
||||
public class CustomDefaultSnippets {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation("build");
|
||||
|
||||
RequestSpecification spec;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
// tag::custom-default-snippets[]
|
||||
this.spec = new RequestSpecBuilder()
|
||||
.addFilter(documentationConfiguration(this.restDocumentation)
|
||||
.snippets().withDefaults(curlRequest()))
|
||||
.build();
|
||||
// end::custom-default-snippets[]
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
|
||||
import com.jayway.restassured.builder.RequestSpecBuilder;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration;
|
||||
|
||||
public class CustomEncoding {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation("build");
|
||||
|
||||
private RequestSpecification spec;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
// tag::custom-encoding[]
|
||||
this.spec = new RequestSpecBuilder()
|
||||
.addFilter(documentationConfiguration(this.restDocumentation)
|
||||
.snippets().withEncoding("ISO-8859-1"))
|
||||
.build();
|
||||
// end::custom-encoding[]
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.restdocs.restassured.RestDocumentationFilter;
|
||||
|
||||
import com.jayway.restassured.RestAssured;
|
||||
import com.jayway.restassured.builder.RequestSpecBuilder;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
|
||||
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.removeHeaders;
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration;
|
||||
|
||||
public class EveryTestPreprocessing {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation(
|
||||
"target/generated-snippets");
|
||||
|
||||
// tag::setup[]
|
||||
private RequestSpecification spec;
|
||||
|
||||
private RestDocumentationFilter document;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.document = document("{method-name}",
|
||||
preprocessRequest(removeHeaders("Foo")),
|
||||
preprocessResponse(prettyPrint())); // <1>
|
||||
this.spec = new RequestSpecBuilder()
|
||||
.addFilter(documentationConfiguration(this.restDocumentation))
|
||||
.addFilter(this.document)// <2>
|
||||
.build();
|
||||
}
|
||||
|
||||
// end::setup[]
|
||||
|
||||
public void use() throws Exception {
|
||||
// tag::use[]
|
||||
this.document.snippets( // <1>
|
||||
links(linkWithRel("self").description("Canonical self link")));
|
||||
RestAssured.given(this.spec) // <2>
|
||||
.when().get("/")
|
||||
.then().assertThat().statusCode(is(200));
|
||||
// end::use[]
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
|
||||
import com.jayway.restassured.builder.RequestSpecBuilder;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration;
|
||||
|
||||
public class ExampleApplicationTests {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation(
|
||||
"build/generated-snippets");
|
||||
|
||||
// tag::setup[]
|
||||
private RequestSpecification spec;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.spec = new RequestSpecBuilder().addFilter(
|
||||
documentationConfiguration(this.restDocumentation)) // <1>
|
||||
.build();
|
||||
}
|
||||
// end::setup[]
|
||||
}
|
||||
51
docs/src/test/java/com/example/restassured/HttpHeaders.java
Normal file
51
docs/src/test/java/com/example/restassured/HttpHeaders.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import com.jayway.restassured.RestAssured;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName;
|
||||
import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders;
|
||||
import static org.springframework.restdocs.headers.HeaderDocumentation.responseHeaders;
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;
|
||||
|
||||
public class HttpHeaders {
|
||||
|
||||
private RequestSpecification spec;
|
||||
|
||||
public void headers() throws Exception {
|
||||
// tag::headers[]
|
||||
RestAssured.given(this.spec)
|
||||
.filter(document("headers",
|
||||
requestHeaders( // <1>
|
||||
headerWithName("Authorization").description(
|
||||
"Basic auth credentials")), // <2>
|
||||
responseHeaders( // <3>
|
||||
headerWithName("X-RateLimit-Limit").description(
|
||||
"The total number of requests permitted per period"),
|
||||
headerWithName("X-RateLimit-Remaining").description(
|
||||
"Remaining requests permitted in current period"),
|
||||
headerWithName("X-RateLimit-Reset").description(
|
||||
"Time at which the rate limit period will reset"))))
|
||||
.header("Authroization", "Basic dXNlcjpzZWNyZXQ=") // <4>
|
||||
.when().get("/people")
|
||||
.then().assertThat().statusCode(is(200));
|
||||
// end::headers[]
|
||||
}
|
||||
}
|
||||
54
docs/src/test/java/com/example/restassured/Hypermedia.java
Normal file
54
docs/src/test/java/com/example/restassured/Hypermedia.java
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import com.jayway.restassured.RestAssured;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.halLinks;
|
||||
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
|
||||
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;
|
||||
|
||||
public class Hypermedia {
|
||||
|
||||
private RequestSpecification spec;
|
||||
|
||||
public void defaultExtractor() throws Exception {
|
||||
// tag::links[]
|
||||
RestAssured.given(this.spec)
|
||||
.accept("application/json")
|
||||
.filter(document("index", links( // <1>
|
||||
linkWithRel("alpha").description("Link to the alpha resource"), // <2>
|
||||
linkWithRel("bravo").description("Link to the bravo resource")))) // <3>
|
||||
.get("/").then().assertThat().statusCode(is(200));
|
||||
// end::links[]
|
||||
}
|
||||
|
||||
public void explicitExtractor() throws Exception {
|
||||
RestAssured.given(this.spec)
|
||||
.accept("application/json")
|
||||
// tag::explicit-extractor[]
|
||||
.filter(document("index", links(halLinks(), // <1>
|
||||
linkWithRel("alpha").description("Link to the alpha resource"),
|
||||
linkWithRel("bravo").description("Link to the bravo resource"))))
|
||||
// end::explicit-extractor[]
|
||||
.get("/").then().assertThat().statusCode(is(200));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import com.jayway.restassured.RestAssured;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;
|
||||
|
||||
public class InvokeService {
|
||||
|
||||
private RequestSpecification spec;
|
||||
|
||||
public void invokeService() throws Exception {
|
||||
// tag::invoke-service[]
|
||||
RestAssured.given(this.spec) // <1>
|
||||
.accept("application/json") // <2>
|
||||
.filter(document("index")) // <3>
|
||||
.when().get("/") // <4>
|
||||
.then().assertThat().statusCode(is(200)); // <5>
|
||||
// end::invoke-service[]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
|
||||
import com.jayway.restassured.builder.RequestSpecBuilder;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration;
|
||||
|
||||
public class ParameterizedOutput {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation(
|
||||
"build/generated-snippets");
|
||||
|
||||
private RequestSpecification spec;
|
||||
|
||||
// tag::parameterized-output[]
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.spec = new RequestSpecBuilder()
|
||||
.addFilter(documentationConfiguration(this.restDocumentation))
|
||||
.addFilter(document("{method-name}/{step}")).build();
|
||||
}
|
||||
// end::parameterized-output[]
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import com.jayway.restassured.RestAssured;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.pathParameters;
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;
|
||||
|
||||
public class PathParameters {
|
||||
|
||||
private RequestSpecification spec;
|
||||
|
||||
public void pathParametersSnippet() throws Exception {
|
||||
// tag::path-parameters[]
|
||||
RestAssured.given(this.spec)
|
||||
.filter(document("locations", pathParameters( // <1>
|
||||
parameterWithName("latitude").description("The location's latitude"), // <2>
|
||||
parameterWithName("longitude").description("The location's longitude")))) // <3>
|
||||
.when().get("/locations/{latitude}/{longitude}", 51.5072, 0.1275) // <4>
|
||||
.then().assertThat().statusCode(is(200));
|
||||
// end::path-parameters[]
|
||||
}
|
||||
}
|
||||
75
docs/src/test/java/com/example/restassured/Payload.java
Normal file
75
docs/src/test/java/com/example/restassured/Payload.java
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import org.springframework.restdocs.payload.JsonFieldType;
|
||||
|
||||
import com.jayway.restassured.RestAssured;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
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.restassured.RestAssuredRestDocumentation.document;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
|
||||
public class Payload {
|
||||
|
||||
private RequestSpecification spec;
|
||||
|
||||
public void response() throws Exception {
|
||||
// tag::response[]
|
||||
RestAssured.given(this.spec).accept("application/json")
|
||||
.filter(document("user", responseFields( // <1>
|
||||
fieldWithPath("contact").description("The user's contact details"), // <2>
|
||||
fieldWithPath("contact.email").description("The user's email address")))) // <3>
|
||||
.when().get("/user/5")
|
||||
.then().assertThat().statusCode(is(200));
|
||||
// end::response[]
|
||||
}
|
||||
|
||||
public void explicitType() throws Exception {
|
||||
RestAssured.given(this.spec).accept("application/json")
|
||||
// tag::explicit-type[]
|
||||
.filter(document("user", responseFields(
|
||||
fieldWithPath("contact.email")
|
||||
.type(JsonFieldType.STRING) // <1>
|
||||
.description("The user's email address"))))
|
||||
// end::explicit-type[]
|
||||
.when().get("/user/5")
|
||||
.then().assertThat().statusCode(is(200));
|
||||
}
|
||||
|
||||
public void constraints() throws Exception {
|
||||
RestAssured.given(this.spec).accept("application/json")
|
||||
// tag::constraints[]
|
||||
.filter(document("create-user", requestFields(
|
||||
attributes(key("title").value("Fields for user creation")), // <1>
|
||||
fieldWithPath("name").description("The user's name")
|
||||
.attributes(key("constraints")
|
||||
.value("Must not be null. Must not be empty")), // <2>
|
||||
fieldWithPath("email").description("The user's email address")
|
||||
.attributes(key("constraints")
|
||||
.value("Must be a valid email address"))))) // <3>
|
||||
// end::constraints[]
|
||||
.when().post("/users")
|
||||
.then().assertThat().statusCode(is(200));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import com.jayway.restassured.RestAssured;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.removeHeaders;
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;
|
||||
|
||||
public class PerTestPreprocessing {
|
||||
|
||||
private RequestSpecification spec;
|
||||
|
||||
public void general() throws Exception {
|
||||
// tag::preprocessing[]
|
||||
RestAssured.given(this.spec)
|
||||
.filter(document("index", preprocessRequest(removeHeaders("Foo")), // <1>
|
||||
preprocessResponse(prettyPrint()))) // <2>
|
||||
.when().get("/")
|
||||
.then().assertThat().statusCode(is(200));
|
||||
// end::preprocessing[]
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import com.jayway.restassured.RestAssured;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;
|
||||
|
||||
public class RequestParameters {
|
||||
|
||||
private RequestSpecification spec;
|
||||
|
||||
public void getQueryStringSnippet() throws Exception {
|
||||
// tag::request-parameters-query-string[]
|
||||
RestAssured.given(this.spec)
|
||||
.filter(document("users", requestParameters( // <1>
|
||||
parameterWithName("page").description("The page to retrieve"), // <2>
|
||||
parameterWithName("per_page").description("Entries per page")))) // <3>
|
||||
.when().get("/users?page=2&per_page=100") // <4>
|
||||
.then().assertThat().statusCode(is(200));
|
||||
// end::request-parameters-query-string[]
|
||||
}
|
||||
|
||||
public void postFormDataSnippet() throws Exception {
|
||||
// tag::request-parameters-form-data[]
|
||||
RestAssured.given(this.spec)
|
||||
.filter(document("create-user", requestParameters(
|
||||
parameterWithName("username").description("The user's username"))))
|
||||
.formParam("username", "Tester") // <1>
|
||||
.when().post("/users") // <2>
|
||||
.then().assertThat().statusCode(is(200));
|
||||
// end::request-parameters-form-data[]
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,4 +2,5 @@ rootProject.name = 'spring-restdocs'
|
||||
|
||||
include 'docs'
|
||||
include 'spring-restdocs-core'
|
||||
include 'spring-restdocs-mockmvc'
|
||||
include 'spring-restdocs-mockmvc'
|
||||
include 'spring-restdocs-restassured'
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -14,9 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.mockmvc;
|
||||
package org.springframework.restdocs.config;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.restdocs.RestDocumentationContext;
|
||||
|
||||
/**
|
||||
* Abstract configurer that declares methods that are internal to the documentation
|
||||
@@ -24,13 +26,15 @@ import org.springframework.mock.web.MockHttpServletRequest;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
abstract class AbstractConfigurer {
|
||||
public abstract class AbstractConfigurer {
|
||||
|
||||
/**
|
||||
* Applies the configuration, possibly by modifying the given {@code request}.
|
||||
* Applies the configurer to the given {@code configuration}.
|
||||
*
|
||||
* @param request the request that may be modified
|
||||
* @param configuration the configuration to be configured
|
||||
* @param context the current documentation context
|
||||
*/
|
||||
abstract void apply(MockHttpServletRequest request);
|
||||
public abstract void apply(Map<String, Object> configuration,
|
||||
RestDocumentationContext context);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.config;
|
||||
|
||||
/**
|
||||
* Base class for {@link NestedConfigurer} implementations.
|
||||
*
|
||||
* @param <P> The type of the configurer's parent
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public abstract class AbstractNestedConfigurer<P> extends AbstractConfigurer implements
|
||||
NestedConfigurer<P> {
|
||||
|
||||
private final P parent;
|
||||
|
||||
/**
|
||||
* Creates a new {@code AbstractNestedConfigurer} with the given {@code parent}.
|
||||
* @param parent the parent
|
||||
*/
|
||||
protected AbstractNestedConfigurer(P parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final P and() {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -14,22 +14,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.mockmvc;
|
||||
|
||||
import org.springframework.test.web.servlet.setup.MockMvcConfigurer;
|
||||
package org.springframework.restdocs.config;
|
||||
|
||||
/**
|
||||
* A configurer that is nested and, therefore, has a parent.
|
||||
*
|
||||
* @param <PARENT> The parent's type
|
||||
* @param <P> The parent's type
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
interface NestedConfigurer<PARENT extends MockMvcConfigurer> {
|
||||
interface NestedConfigurer<P> {
|
||||
|
||||
/**
|
||||
* Returns the configurer's parent.
|
||||
*
|
||||
* @return the parent
|
||||
*/
|
||||
PARENT and();
|
||||
P and();
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.config;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.restdocs.RestDocumentationContext;
|
||||
import org.springframework.restdocs.snippet.RestDocumentationContextPlaceholderResolver;
|
||||
import org.springframework.restdocs.snippet.StandardWriterResolver;
|
||||
import org.springframework.restdocs.snippet.WriterResolver;
|
||||
import org.springframework.restdocs.templates.StandardTemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
|
||||
/**
|
||||
* Abstract base class for the configuration of Spring REST Docs.
|
||||
*
|
||||
* @param <S> The concrete type of the {@link SnippetConfigurer}.
|
||||
* @param <T> The concrete type of this configurer, to be returned from methods that
|
||||
* support chaining
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public abstract class RestDocumentationConfigurer<S, T> {
|
||||
|
||||
private final WriterResolverConfigurer writerResolverConfigurer = new WriterResolverConfigurer();
|
||||
|
||||
private final TemplateEngineConfigurer templateEngineConfigurer = new TemplateEngineConfigurer();
|
||||
|
||||
/**
|
||||
* Returns a {@link SnippetConfigurer} that can be used to configure the snippets that
|
||||
* will be generated.
|
||||
*
|
||||
* @return the snippet configurer
|
||||
*/
|
||||
public abstract S snippets();
|
||||
|
||||
/**
|
||||
* Configures the {@link TemplateEngine} that will be used for snippet rendering.
|
||||
*
|
||||
* @param templateEngine the template engine to use
|
||||
* @return {@code this}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final T templateEngine(TemplateEngine templateEngine) {
|
||||
this.templateEngineConfigurer.setTemplateEngine(templateEngine);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link WriterResolver} that will be used to resolve a writer for a
|
||||
* snippet.
|
||||
*
|
||||
* @param writerResolver The writer resolver to use
|
||||
* @return {@code this}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final T writerResolver(WriterResolver writerResolver) {
|
||||
this.writerResolverConfigurer.setWriterResolver(writerResolver);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configurer used to configure the context with a {@link WriterResolver}.
|
||||
*
|
||||
* @return the configurer
|
||||
*/
|
||||
protected final AbstractConfigurer getWriterResolverConfigurer() {
|
||||
return this.writerResolverConfigurer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configurer used to configure the context with a {@link TemplateEngine}.
|
||||
*
|
||||
* @return the configurer
|
||||
*/
|
||||
protected final AbstractConfigurer getTemplateEngineConfigurer() {
|
||||
return this.templateEngineConfigurer;
|
||||
}
|
||||
|
||||
private static final class TemplateEngineConfigurer extends AbstractConfigurer {
|
||||
|
||||
private TemplateEngine templateEngine = new MustacheTemplateEngine(
|
||||
new StandardTemplateResourceResolver());
|
||||
|
||||
@Override
|
||||
public void apply(Map<String, Object> configuration,
|
||||
RestDocumentationContext context) {
|
||||
configuration.put(TemplateEngine.class.getName(), this.templateEngine);
|
||||
}
|
||||
|
||||
private void setTemplateEngine(TemplateEngine templateEngine) {
|
||||
this.templateEngine = templateEngine;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class WriterResolverConfigurer extends AbstractConfigurer {
|
||||
|
||||
private WriterResolver writerResolver;
|
||||
|
||||
@Override
|
||||
public void apply(Map<String, Object> configuration,
|
||||
RestDocumentationContext context) {
|
||||
WriterResolver resolverToUse = this.writerResolver;
|
||||
if (resolverToUse == null) {
|
||||
resolverToUse = new StandardWriterResolver(
|
||||
new RestDocumentationContextPlaceholderResolver(context));
|
||||
}
|
||||
configuration.put(WriterResolver.class.getName(), resolverToUse);
|
||||
}
|
||||
|
||||
private void setWriterResolver(WriterResolver writerResolver) {
|
||||
this.writerResolver = writerResolver;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -14,12 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.mockmvc;
|
||||
package org.springframework.restdocs.config;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.restdocs.RestDocumentationContext;
|
||||
import org.springframework.restdocs.curl.CurlDocumentation;
|
||||
import org.springframework.restdocs.http.HttpDocumentation;
|
||||
import org.springframework.restdocs.snippet.Snippet;
|
||||
@@ -28,10 +29,16 @@ import org.springframework.restdocs.snippet.WriterResolver;
|
||||
/**
|
||||
* A configurer that can be used to configure the generated documentation snippets.
|
||||
*
|
||||
* @param <P> The type of the configurer's parent
|
||||
* @param <T> The concrete type of the configurer to be returned from chained methods
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class SnippetConfigurer extends
|
||||
AbstractNestedConfigurer<RestDocumentationMockMvcConfigurer> {
|
||||
public abstract class SnippetConfigurer<P, T> extends AbstractNestedConfigurer<P> {
|
||||
|
||||
/**
|
||||
* The name of the attribute that is used to hold the default snippets.
|
||||
*/
|
||||
public static final String ATTRIBUTE_DEFAULT_SNIPPETS = "org.springframework.restdocs.defaultSnippets";
|
||||
|
||||
private List<Snippet> defaultSnippets = Arrays.asList(
|
||||
CurlDocumentation.curlRequest(), HttpDocumentation.httpRequest(),
|
||||
@@ -46,10 +53,22 @@ public class SnippetConfigurer extends
|
||||
|
||||
private String snippetEncoding = DEFAULT_SNIPPET_ENCODING;
|
||||
|
||||
SnippetConfigurer(RestDocumentationMockMvcConfigurer parent) {
|
||||
/**
|
||||
* Creates a new {@code SnippetConfigurer} with the given {@code parent}.
|
||||
*
|
||||
* @param parent the parent
|
||||
*/
|
||||
protected SnippetConfigurer(P parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Map<String, Object> configuration, RestDocumentationContext context) {
|
||||
((WriterResolver) configuration.get(WriterResolver.class.getName()))
|
||||
.setEncoding(this.snippetEncoding);
|
||||
configuration.put(ATTRIBUTE_DEFAULT_SNIPPETS, this.defaultSnippets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures any documentation snippets to be written using the given
|
||||
* {@code encoding}. The default is UTF-8.
|
||||
@@ -57,17 +76,10 @@ public class SnippetConfigurer extends
|
||||
* @param encoding the encoding
|
||||
* @return {@code this}
|
||||
*/
|
||||
public SnippetConfigurer withEncoding(String encoding) {
|
||||
@SuppressWarnings("unchecked")
|
||||
public T withEncoding(String encoding) {
|
||||
this.snippetEncoding = encoding;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
void apply(MockHttpServletRequest request) {
|
||||
((WriterResolver) request.getAttribute(WriterResolver.class.getName()))
|
||||
.setEncoding(this.snippetEncoding);
|
||||
request.setAttribute("org.springframework.restdocs.mockmvc.defaultSnippets",
|
||||
this.defaultSnippets);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,8 +88,9 @@ public class SnippetConfigurer extends
|
||||
* @param defaultSnippets the default snippets
|
||||
* @return {@code this}
|
||||
*/
|
||||
public SnippetConfigurer withDefaults(Snippet... defaultSnippets) {
|
||||
@SuppressWarnings("unchecked")
|
||||
public T withDefaults(Snippet... defaultSnippets) {
|
||||
this.defaultSnippets = Arrays.asList(defaultSnippets);
|
||||
return this;
|
||||
return (T) this;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -92,8 +92,9 @@ public class PathParametersSnippet extends AbstractParametersSnippet {
|
||||
private String extractUrlTemplate(Operation operation) {
|
||||
String urlTemplate = (String) operation.getAttributes().get(
|
||||
"org.springframework.restdocs.urlTemplate");
|
||||
Assert.notNull(urlTemplate,
|
||||
"urlTemplate not found. Did you use RestDocumentationRequestBuilders to "
|
||||
Assert.notNull(
|
||||
urlTemplate,
|
||||
"urlTemplate not found. If you are using MockMvc, did you use RestDocumentationRequestBuilders to "
|
||||
+ "build the request?");
|
||||
return urlTemplate;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -44,9 +44,9 @@ public abstract class MockMvcRestDocumentation {
|
||||
* @return the configurer
|
||||
* @see ConfigurableMockMvcBuilder#apply(MockMvcConfigurer)
|
||||
*/
|
||||
public static RestDocumentationMockMvcConfigurer documentationConfiguration(
|
||||
public static MockMvcRestDocumentationConfigurer documentationConfiguration(
|
||||
RestDocumentation restDocumentation) {
|
||||
return new RestDocumentationMockMvcConfigurer(restDocumentation);
|
||||
return new MockMvcRestDocumentationConfigurer(restDocumentation);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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.mockmvc;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentationContext;
|
||||
import org.springframework.restdocs.config.AbstractConfigurer;
|
||||
import org.springframework.restdocs.config.RestDocumentationConfigurer;
|
||||
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
||||
import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcConfigurer;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
/**
|
||||
* A MockMvc-specific {@link RestDocumentationConfigurer}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class MockMvcRestDocumentationConfigurer
|
||||
extends
|
||||
RestDocumentationConfigurer<MockMvcSnippetConfigurer, MockMvcRestDocumentationConfigurer>
|
||||
implements MockMvcConfigurer {
|
||||
|
||||
private final MockMvcSnippetConfigurer snippetConfigurer = new MockMvcSnippetConfigurer(
|
||||
this);
|
||||
|
||||
private final UriConfigurer uriConfigurer = new UriConfigurer(this);
|
||||
|
||||
private final RestDocumentation restDocumentation;
|
||||
|
||||
MockMvcRestDocumentationConfigurer(RestDocumentation restDocumentation) {
|
||||
super();
|
||||
this.restDocumentation = restDocumentation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link UriConfigurer} that can be used to configure the request URIs that
|
||||
* will be documented.
|
||||
*
|
||||
* @return the URI configurer
|
||||
*/
|
||||
public UriConfigurer uris() {
|
||||
return this.uriConfigurer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestPostProcessor beforeMockMvcCreated(
|
||||
ConfigurableMockMvcBuilder<?> builder, WebApplicationContext context) {
|
||||
return new ConfigurerApplyingRequestPostProcessor(this.restDocumentation,
|
||||
Arrays.asList(getTemplateEngineConfigurer(),
|
||||
getWriterResolverConfigurer(), snippets(), this.uriConfigurer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConfigurerAdded(ConfigurableMockMvcBuilder<?> builder) {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockMvcSnippetConfigurer snippets() {
|
||||
return this.snippetConfigurer;
|
||||
}
|
||||
|
||||
private static final class ConfigurerApplyingRequestPostProcessor implements
|
||||
RequestPostProcessor {
|
||||
|
||||
private final RestDocumentation restDocumentation;
|
||||
|
||||
private final List<AbstractConfigurer> configurers;
|
||||
|
||||
private ConfigurerApplyingRequestPostProcessor(
|
||||
RestDocumentation restDocumentation, List<AbstractConfigurer> configurers) {
|
||||
this.restDocumentation = restDocumentation;
|
||||
this.configurers = configurers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
|
||||
RestDocumentationContext context = this.restDocumentation.beforeOperation();
|
||||
request.setAttribute(RestDocumentationContext.class.getName(), context);
|
||||
Map<String, Object> configuration = new HashMap<>();
|
||||
configuration.put(MockHttpServletRequest.class.getName(), request);
|
||||
String urlTemplateAttribute = "org.springframework.restdocs.urlTemplate";
|
||||
configuration.put(urlTemplateAttribute,
|
||||
request.getAttribute(urlTemplateAttribute));
|
||||
request.setAttribute("org.springframework.restdocs.configuration",
|
||||
configuration);
|
||||
for (AbstractConfigurer configurer : this.configurers) {
|
||||
configurer.apply(configuration, context);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -16,40 +16,33 @@
|
||||
|
||||
package org.springframework.restdocs.mockmvc;
|
||||
|
||||
import org.springframework.restdocs.config.SnippetConfigurer;
|
||||
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
||||
import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcConfigurer;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
/**
|
||||
* Base class for {@link NestedConfigurer} implementations.
|
||||
* A configurer that can be used to configure the generated documentation snippets.
|
||||
*
|
||||
* @param <PARENT> The type of the configurer's parent
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
abstract class AbstractNestedConfigurer<PARENT extends MockMvcConfigurer> extends
|
||||
AbstractConfigurer implements NestedConfigurer<PARENT>, MockMvcConfigurer {
|
||||
public class MockMvcSnippetConfigurer extends
|
||||
SnippetConfigurer<MockMvcRestDocumentationConfigurer, MockMvcSnippetConfigurer>
|
||||
implements MockMvcConfigurer {
|
||||
|
||||
private final PARENT parent;
|
||||
|
||||
protected AbstractNestedConfigurer(PARENT parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PARENT and() {
|
||||
return this.parent;
|
||||
MockMvcSnippetConfigurer(MockMvcRestDocumentationConfigurer parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConfigurerAdded(ConfigurableMockMvcBuilder<?> builder) {
|
||||
this.parent.afterConfigurerAdded(builder);
|
||||
and().afterConfigurerAdded(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestPostProcessor beforeMockMvcCreated(
|
||||
ConfigurableMockMvcBuilder<?> builder, WebApplicationContext context) {
|
||||
return this.parent.beforeMockMvcCreated(builder, context);
|
||||
return and().beforeMockMvcCreated(builder, context);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
/*
|
||||
* 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.mockmvc;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentationContext;
|
||||
import org.springframework.restdocs.curl.CurlDocumentation;
|
||||
import org.springframework.restdocs.http.HttpDocumentation;
|
||||
import org.springframework.restdocs.snippet.RestDocumentationContextPlaceholderResolver;
|
||||
import org.springframework.restdocs.snippet.StandardWriterResolver;
|
||||
import org.springframework.restdocs.snippet.WriterResolver;
|
||||
import org.springframework.restdocs.templates.StandardTemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
||||
import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcConfigurer;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcConfigurerAdapter;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
/**
|
||||
* A {@link MockMvcConfigurer} that can be used to configure the documentation.
|
||||
* <p>
|
||||
* In the absence of any {@link #snippets() customization} the following snippets will be
|
||||
* produced by default:
|
||||
* <ul>
|
||||
* <li>{@link CurlDocumentation#curlRequest() Curl request}</li>
|
||||
* <li>{@link HttpDocumentation#httpRequest() HTTP request}</li>
|
||||
* <li>{@link HttpDocumentation#httpResponse() HTTP response}</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* In the absence of any {@link #uris() customization}, documented URIs have the following
|
||||
* defaults:
|
||||
* <ul>
|
||||
* <li>Scheme: {@code http}</li>
|
||||
* <li>Host: {@code localhost}</li>
|
||||
* <li>Port: {@code 8080}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Dmitriy Mayboroda
|
||||
* @see ConfigurableMockMvcBuilder#apply(MockMvcConfigurer)
|
||||
* @see MockMvcRestDocumentation#documentationConfiguration(RestDocumentation)
|
||||
*/
|
||||
public class RestDocumentationMockMvcConfigurer extends MockMvcConfigurerAdapter {
|
||||
|
||||
private final UriConfigurer uriConfigurer = new UriConfigurer(this);
|
||||
|
||||
private final SnippetConfigurer snippetConfigurer = new SnippetConfigurer(this);
|
||||
|
||||
private final RequestPostProcessor requestPostProcessor;
|
||||
|
||||
private final TemplateEngineConfigurer templateEngineConfigurer = new TemplateEngineConfigurer();
|
||||
|
||||
private final WriterResolverConfigurer writerResolverConfigurer = new WriterResolverConfigurer();
|
||||
|
||||
/**
|
||||
* Creates a new {code RestDocumentationMockMvcConfigurer} that will use the given
|
||||
* {@code restDocumentation} when configuring MockMvc.
|
||||
*
|
||||
* @param restDocumentation the rest documentation
|
||||
* @see MockMvcRestDocumentation#documentationConfiguration(RestDocumentation)
|
||||
*/
|
||||
RestDocumentationMockMvcConfigurer(RestDocumentation restDocumentation) {
|
||||
this.requestPostProcessor = new ConfigurerApplyingRequestPostProcessor(
|
||||
restDocumentation, this.uriConfigurer, this.writerResolverConfigurer,
|
||||
this.snippetConfigurer, this.templateEngineConfigurer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link UriConfigurer} that can be used to configure the request URIs that
|
||||
* will be documented.
|
||||
*
|
||||
* @return the URI configurer
|
||||
*/
|
||||
public UriConfigurer uris() {
|
||||
return this.uriConfigurer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link SnippetConfigurer} that can be used to configure the snippets that
|
||||
* will be generated.
|
||||
*
|
||||
* @return the snippet configurer
|
||||
*/
|
||||
public SnippetConfigurer snippets() {
|
||||
return this.snippetConfigurer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link TemplateEngine} that will be used for snippet rendering.
|
||||
*
|
||||
* @param templateEngine the template engine to use
|
||||
* @return {@code this}
|
||||
*/
|
||||
public RestDocumentationMockMvcConfigurer templateEngine(TemplateEngine templateEngine) {
|
||||
this.templateEngineConfigurer.setTemplateEngine(templateEngine);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link WriterResolver} that will be used to resolve a writer for a
|
||||
* snippet.
|
||||
*
|
||||
* @param writerResolver The writer resolver to use
|
||||
* @return {@code this}
|
||||
*/
|
||||
public RestDocumentationMockMvcConfigurer writerResolver(WriterResolver writerResolver) {
|
||||
this.writerResolverConfigurer.setWriterResolver(writerResolver);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestPostProcessor beforeMockMvcCreated(
|
||||
ConfigurableMockMvcBuilder<?> builder, WebApplicationContext context) {
|
||||
return this.requestPostProcessor;
|
||||
}
|
||||
|
||||
private static final class TemplateEngineConfigurer extends AbstractConfigurer {
|
||||
|
||||
private TemplateEngine templateEngine = new MustacheTemplateEngine(
|
||||
new StandardTemplateResourceResolver());
|
||||
|
||||
@Override
|
||||
void apply(MockHttpServletRequest request) {
|
||||
request.setAttribute(TemplateEngine.class.getName(), this.templateEngine);
|
||||
}
|
||||
|
||||
void setTemplateEngine(TemplateEngine templateEngine) {
|
||||
this.templateEngine = templateEngine;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class WriterResolverConfigurer extends AbstractConfigurer {
|
||||
|
||||
private WriterResolver writerResolver;
|
||||
|
||||
@Override
|
||||
void apply(MockHttpServletRequest request) {
|
||||
WriterResolver resolverToUse = this.writerResolver;
|
||||
if (resolverToUse == null) {
|
||||
resolverToUse = new StandardWriterResolver(
|
||||
new RestDocumentationContextPlaceholderResolver(
|
||||
(RestDocumentationContext) request
|
||||
.getAttribute(RestDocumentationContext.class
|
||||
.getName())));
|
||||
}
|
||||
request.setAttribute(WriterResolver.class.getName(), resolverToUse);
|
||||
}
|
||||
|
||||
void setWriterResolver(WriterResolver writerResolver) {
|
||||
this.writerResolver = writerResolver;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class ConfigurerApplyingRequestPostProcessor implements
|
||||
RequestPostProcessor {
|
||||
|
||||
private final RestDocumentation restDocumentation;
|
||||
|
||||
private final AbstractConfigurer[] configurers;
|
||||
|
||||
private ConfigurerApplyingRequestPostProcessor(
|
||||
RestDocumentation restDocumentation, AbstractConfigurer... configurers) {
|
||||
this.restDocumentation = restDocumentation;
|
||||
this.configurers = configurers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
|
||||
request.setAttribute(RestDocumentationContext.class.getName(),
|
||||
this.restDocumentation.beforeOperation());
|
||||
for (AbstractConfigurer configurer : this.configurers) {
|
||||
configurer.apply(request);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -22,6 +22,8 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.restdocs.RestDocumentationContext;
|
||||
import org.springframework.restdocs.config.SnippetConfigurer;
|
||||
import org.springframework.restdocs.operation.Operation;
|
||||
import org.springframework.restdocs.operation.OperationRequest;
|
||||
import org.springframework.restdocs.operation.OperationResponse;
|
||||
@@ -33,8 +35,6 @@ import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.ResultHandler;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.IterableEnumeration.iterable;
|
||||
|
||||
/**
|
||||
* A Spring MVC Test {@code ResultHandler} for documenting RESTful APIs.
|
||||
*
|
||||
@@ -85,9 +85,15 @@ public class RestDocumentationResultHandler implements ResultHandler {
|
||||
@Override
|
||||
public void handle(MvcResult result) throws Exception {
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
for (String name : iterable(result.getRequest().getAttributeNames())) {
|
||||
attributes.put(name, result.getRequest().getAttribute(name));
|
||||
}
|
||||
attributes.put(RestDocumentationContext.class.getName(), result.getRequest()
|
||||
.getAttribute(RestDocumentationContext.class.getName()));
|
||||
attributes.put("org.springframework.restdocs.urlTemplate", result.getRequest()
|
||||
.getAttribute("org.springframework.restdocs.urlTemplate"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> configuration = (Map<String, Object>) result.getRequest()
|
||||
.getAttribute("org.springframework.restdocs.configuration");
|
||||
attributes.putAll(configuration);
|
||||
|
||||
OperationRequest request = this.requestPreprocessor
|
||||
.preprocess(new MockMvcOperationRequestFactory()
|
||||
.createOperationRequest(result.getRequest()));
|
||||
@@ -103,7 +109,7 @@ public class RestDocumentationResultHandler implements ResultHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given {@code snippets} such that that are documented when this result
|
||||
* Adds the given {@code snippets} such that they are documented when this result
|
||||
* handler is called.
|
||||
*
|
||||
* @param snippets the snippets to add
|
||||
@@ -116,9 +122,10 @@ public class RestDocumentationResultHandler implements ResultHandler {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<Snippet> getSnippets(MvcResult result) {
|
||||
List<Snippet> combinedSnippets = new ArrayList<>((List<Snippet>) result
|
||||
.getRequest().getAttribute(
|
||||
"org.springframework.restdocs.mockmvc.defaultSnippets"));
|
||||
List<Snippet> combinedSnippets = new ArrayList<>(
|
||||
(List<Snippet>) ((Map<String, Object>) result.getRequest().getAttribute(
|
||||
"org.springframework.restdocs.configuration"))
|
||||
.get(SnippetConfigurer.ATTRIBUTE_DEFAULT_SNIPPETS));
|
||||
combinedSnippets.addAll(this.snippets);
|
||||
return combinedSnippets;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -16,7 +16,15 @@
|
||||
|
||||
package org.springframework.restdocs.mockmvc;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.restdocs.RestDocumentationContext;
|
||||
import org.springframework.restdocs.config.AbstractNestedConfigurer;
|
||||
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
||||
import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcConfigurer;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
/**
|
||||
* A configurer that can be used to configure the documented URIs.
|
||||
@@ -24,7 +32,8 @@ import org.springframework.mock.web.MockHttpServletRequest;
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class UriConfigurer extends
|
||||
AbstractNestedConfigurer<RestDocumentationMockMvcConfigurer> {
|
||||
AbstractNestedConfigurer<MockMvcRestDocumentationConfigurer> implements
|
||||
MockMvcConfigurer {
|
||||
|
||||
/**
|
||||
* The default scheme for documented URIs.
|
||||
@@ -53,7 +62,7 @@ public class UriConfigurer extends
|
||||
|
||||
private int port = DEFAULT_PORT;
|
||||
|
||||
UriConfigurer(RestDocumentationMockMvcConfigurer parent) {
|
||||
UriConfigurer(MockMvcRestDocumentationConfigurer parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
@@ -94,10 +103,23 @@ public class UriConfigurer extends
|
||||
}
|
||||
|
||||
@Override
|
||||
void apply(MockHttpServletRequest request) {
|
||||
public void apply(Map<String, Object> configuration, RestDocumentationContext context) {
|
||||
MockHttpServletRequest request = (MockHttpServletRequest) configuration
|
||||
.get(MockHttpServletRequest.class.getName());
|
||||
request.setScheme(this.scheme);
|
||||
request.setServerPort(this.port);
|
||||
request.setServerName(this.host);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConfigurerAdded(ConfigurableMockMvcBuilder<?> builder) {
|
||||
and().afterConfigurerAdded(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestPostProcessor beforeMockMvcCreated(
|
||||
ConfigurableMockMvcBuilder<?> builder, WebApplicationContext context) {
|
||||
return and().beforeMockMvcCreated(builder, context);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -33,12 +33,12 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link RestDocumentationMockMvcConfigurer}.
|
||||
* Tests for {@link MockMvcRestDocumentationConfigurer}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Dmitriy Mayboroda
|
||||
*/
|
||||
public class RestDocumentationConfigurerTests {
|
||||
public class MockMvcRestDocumentationConfigurerTests {
|
||||
|
||||
private MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
@@ -47,7 +47,7 @@ public class RestDocumentationConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void defaultConfiguration() {
|
||||
RequestPostProcessor postProcessor = new RestDocumentationMockMvcConfigurer(
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(
|
||||
this.restDocumentation).beforeMockMvcCreated(null, null);
|
||||
postProcessor.postProcessRequest(this.request);
|
||||
|
||||
@@ -56,7 +56,7 @@ public class RestDocumentationConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void customScheme() {
|
||||
RequestPostProcessor postProcessor = new RestDocumentationMockMvcConfigurer(
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(
|
||||
this.restDocumentation).uris().withScheme("https")
|
||||
.beforeMockMvcCreated(null, null);
|
||||
postProcessor.postProcessRequest(this.request);
|
||||
@@ -66,7 +66,7 @@ public class RestDocumentationConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void customHost() {
|
||||
RequestPostProcessor postProcessor = new RestDocumentationMockMvcConfigurer(
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(
|
||||
this.restDocumentation).uris().withHost("api.example.com")
|
||||
.beforeMockMvcCreated(null, null);
|
||||
postProcessor.postProcessRequest(this.request);
|
||||
@@ -76,7 +76,7 @@ public class RestDocumentationConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void customPort() {
|
||||
RequestPostProcessor postProcessor = new RestDocumentationMockMvcConfigurer(
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(
|
||||
this.restDocumentation).uris().withPort(8081)
|
||||
.beforeMockMvcCreated(null, null);
|
||||
postProcessor.postProcessRequest(this.request);
|
||||
@@ -86,7 +86,7 @@ public class RestDocumentationConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void noContentLengthHeaderWhenRequestHasNotContent() {
|
||||
RequestPostProcessor postProcessor = new RestDocumentationMockMvcConfigurer(
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(
|
||||
this.restDocumentation).uris().withPort(8081)
|
||||
.beforeMockMvcCreated(null, null);
|
||||
postProcessor.postProcessRequest(this.request);
|
||||
@@ -83,7 +83,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* Integration tests for using Spring REST Docs with Spring Test's Mock MVC.
|
||||
* Integration tests for using Spring REST Docs with Spring Test's MockMvc.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Dewet Diener
|
||||
@@ -112,8 +112,10 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void basicSnippetGeneration() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation)).build();
|
||||
MockMvc mockMvc = MockMvcBuilders
|
||||
.webAppContextSetup(this.context)
|
||||
.apply(new MockMvcRestDocumentationConfigurer(this.restDocumentation)
|
||||
.snippets().withEncoding("UTF-8")).build();
|
||||
|
||||
mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andDo(document("basic"));
|
||||
|
||||
16
spring-restdocs-restassured/build.gradle
Normal file
16
spring-restdocs-restassured/build.gradle
Normal file
@@ -0,0 +1,16 @@
|
||||
dependencies {
|
||||
compile project(':spring-restdocs-core')
|
||||
compile 'com.jayway.restassured:rest-assured'
|
||||
|
||||
testCompile 'org.mockito:mockito-core'
|
||||
testCompile 'org.hamcrest:hamcrest-library'
|
||||
testCompile 'org.springframework.hateoas:spring-hateoas'
|
||||
testCompile 'org.springframework.boot:spring-boot-starter-web:1.2.5.RELEASE'
|
||||
testCompile 'org.springframework:spring-test'
|
||||
testCompile project(path: ':spring-restdocs-core', configuration: 'testArtifacts')
|
||||
testRuntime 'commons-logging:commons-logging:1.2'
|
||||
}
|
||||
|
||||
test {
|
||||
jvmArgs "-javaagent:${configurations.jacoco.asPath}=destfile=${buildDir}/jacoco.exec,includes=org.springframework.restdocs.*"
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.operation.OperationRequest;
|
||||
import org.springframework.restdocs.operation.OperationRequestFactory;
|
||||
import org.springframework.restdocs.operation.OperationRequestPart;
|
||||
import org.springframework.restdocs.operation.OperationRequestPartFactory;
|
||||
import org.springframework.restdocs.operation.Parameters;
|
||||
|
||||
import com.jayway.restassured.response.Header;
|
||||
import com.jayway.restassured.specification.FilterableRequestSpecification;
|
||||
import com.jayway.restassured.specification.MultiPartSpecification;
|
||||
|
||||
/**
|
||||
* A factory for creating an {@link OperationRequest} derived from a REST Assured
|
||||
* {@link FilterableRequestSpecification}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class RestAssuredOperationRequestFactory {
|
||||
|
||||
OperationRequest createOperationRequest(FilterableRequestSpecification requestSpec) {
|
||||
return new OperationRequestFactory().create(URI.create(requestSpec.getURI()),
|
||||
HttpMethod.valueOf(requestSpec.getMethod().name()),
|
||||
extractContent(requestSpec), extractHeaders(requestSpec),
|
||||
extractParameters(requestSpec), extractParts(requestSpec));
|
||||
}
|
||||
|
||||
private byte[] extractContent(FilterableRequestSpecification requestSpec) {
|
||||
return convertContent(requestSpec.getBody());
|
||||
}
|
||||
|
||||
private byte[] convertContent(Object content) {
|
||||
if (content instanceof String) {
|
||||
return ((String) content).getBytes();
|
||||
}
|
||||
else if (content instanceof byte[]) {
|
||||
return (byte[]) content;
|
||||
}
|
||||
else if (content == null) {
|
||||
return new byte[0];
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unsupported request content: "
|
||||
+ content.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
private HttpHeaders extractHeaders(FilterableRequestSpecification requestSpec) {
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
for (Header header : requestSpec.getHeaders()) {
|
||||
httpHeaders.add(header.getName(), header.getValue());
|
||||
}
|
||||
return httpHeaders;
|
||||
}
|
||||
|
||||
private Parameters extractParameters(FilterableRequestSpecification requestSpec) {
|
||||
Parameters parameters = new Parameters();
|
||||
for (Entry<String, ?> entry : requestSpec.getQueryParams().entrySet()) {
|
||||
parameters.add(entry.getKey(), entry.getValue().toString());
|
||||
}
|
||||
for (Entry<String, ?> entry : requestSpec.getRequestParams().entrySet()) {
|
||||
parameters.add(entry.getKey(), entry.getValue().toString());
|
||||
}
|
||||
for (Entry<String, ?> entry : requestSpec.getFormParams().entrySet()) {
|
||||
parameters.add(entry.getKey(), entry.getValue().toString());
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private Collection<OperationRequestPart> extractParts(
|
||||
FilterableRequestSpecification requestSpec) {
|
||||
List<OperationRequestPart> parts = new ArrayList<>();
|
||||
for (MultiPartSpecification multiPartSpec : requestSpec.getMultiPartParams()) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(multiPartSpec.getMimeType() == null ? MediaType.TEXT_PLAIN
|
||||
: MediaType.parseMediaType(multiPartSpec.getMimeType()));
|
||||
parts.add(new OperationRequestPartFactory().create(
|
||||
multiPartSpec.getControlName(), multiPartSpec.getFileName(),
|
||||
convertContent(multiPartSpec.getContent()), headers));
|
||||
}
|
||||
return parts;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.restdocs.operation.OperationResponse;
|
||||
import org.springframework.restdocs.operation.OperationResponseFactory;
|
||||
|
||||
import com.jayway.restassured.response.Header;
|
||||
import com.jayway.restassured.response.Response;
|
||||
|
||||
/**
|
||||
* A factory for creating an {@link OperationResponse} derived from a REST Assured
|
||||
* {@link Response}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class RestAssuredOperationResponseFactory {
|
||||
|
||||
OperationResponse createOperationResponse(Response response) {
|
||||
return new OperationResponseFactory().create(
|
||||
HttpStatus.valueOf(response.getStatusCode()), extractHeaders(response),
|
||||
extractContent(response));
|
||||
}
|
||||
|
||||
private HttpHeaders extractHeaders(Response response) {
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
for (Header header : response.getHeaders()) {
|
||||
httpHeaders.add(header.getName(), header.getValue());
|
||||
}
|
||||
return httpHeaders;
|
||||
}
|
||||
|
||||
private byte[] extractContent(Response response) {
|
||||
return response.getBody().asByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.restdocs.operation.preprocess.OperationRequestPreprocessor;
|
||||
import org.springframework.restdocs.operation.preprocess.OperationResponsePreprocessor;
|
||||
import org.springframework.restdocs.snippet.Snippet;
|
||||
|
||||
/**
|
||||
* Static factory methods for documenting RESTful APIs using REST Assured.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public abstract class RestAssuredRestDocumentation {
|
||||
|
||||
private RestAssuredRestDocumentation() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Documents the API call with the given {@code identifier} using the given
|
||||
* {@code snippets}.
|
||||
*
|
||||
* @param identifier an identifier for the API call that is being documented
|
||||
* @param snippets the snippets that will document the API call
|
||||
* @return a {@link RestDocumentationFilter} that will produce the documentation
|
||||
*/
|
||||
public static RestDocumentationFilter document(String identifier, Snippet... snippets) {
|
||||
return new RestDocumentationFilter(identifier, snippets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Documents the API call with the given {@code identifier} using the given
|
||||
* {@code snippets} in addition to any default snippets. The given
|
||||
* {@code requestPreprocessor} is applied to the request before it is documented.
|
||||
*
|
||||
* @param identifier an identifier for the API call that is being documented
|
||||
* @param requestPreprocessor the request preprocessor
|
||||
* @param snippets the snippets
|
||||
* @return a {@link RestDocumentationFilter} that will produce the documentation
|
||||
*/
|
||||
public static RestDocumentationFilter document(String identifier,
|
||||
OperationRequestPreprocessor requestPreprocessor, Snippet... snippets) {
|
||||
return new RestDocumentationFilter(identifier, requestPreprocessor, snippets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Documents the API call with the given {@code identifier} using the given
|
||||
* {@code snippets} in addition to any default snippets. The given
|
||||
* {@code responsePreprocessor} is applied to the request before it is documented.
|
||||
*
|
||||
* @param identifier an identifier for the API call that is being documented
|
||||
* @param responsePreprocessor the response preprocessor
|
||||
* @param snippets the snippets
|
||||
* @return a {@link RestDocumentationFilter} that will produce the documentation
|
||||
*/
|
||||
public static RestDocumentationFilter document(String identifier,
|
||||
OperationResponsePreprocessor responsePreprocessor, Snippet... snippets) {
|
||||
return new RestDocumentationFilter(identifier, responsePreprocessor, snippets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Documents the API call with the given {@code identifier} using the given
|
||||
* {@code snippets} in addition to any default snippets. The given
|
||||
* {@code requestPreprocessor} and {@code responsePreprocessor} are applied to the
|
||||
* request and response respectively before they are documented.
|
||||
*
|
||||
* @param identifier an identifier for the API call that is being documented
|
||||
* @param requestPreprocessor the request preprocessor
|
||||
* @param responsePreprocessor the response preprocessor
|
||||
* @param snippets the snippets
|
||||
* @return a {@link RestDocumentationFilter} that will produce the documentation
|
||||
*/
|
||||
public static RestDocumentationFilter document(String identifier,
|
||||
OperationRequestPreprocessor requestPreprocessor,
|
||||
OperationResponsePreprocessor responsePreprocessor, Snippet... snippets) {
|
||||
return new RestDocumentationFilter(identifier, requestPreprocessor,
|
||||
responsePreprocessor, snippets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides access to a {@link RestAssuredRestDocumentationConfigurer} that can be
|
||||
* used to configure Spring REST Docs using the given {@code restDocumentation}.
|
||||
*
|
||||
* @param restDocumentation the REST documentation
|
||||
* @return the configurer
|
||||
*/
|
||||
public static RestAssuredRestDocumentationConfigurer documentationConfiguration(
|
||||
RestDocumentation restDocumentation) {
|
||||
return new RestAssuredRestDocumentationConfigurer(restDocumentation);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentationContext;
|
||||
import org.springframework.restdocs.config.AbstractConfigurer;
|
||||
import org.springframework.restdocs.config.RestDocumentationConfigurer;
|
||||
|
||||
import com.jayway.restassured.filter.Filter;
|
||||
import com.jayway.restassured.filter.FilterContext;
|
||||
import com.jayway.restassured.response.Response;
|
||||
import com.jayway.restassured.specification.FilterableRequestSpecification;
|
||||
import com.jayway.restassured.specification.FilterableResponseSpecification;
|
||||
|
||||
/**
|
||||
* A REST Assured-specific {@link RestDocumentationConfigurer}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public final class RestAssuredRestDocumentationConfigurer
|
||||
extends
|
||||
RestDocumentationConfigurer<RestAssuredSnippetConfigurer, RestAssuredRestDocumentationConfigurer>
|
||||
implements Filter {
|
||||
|
||||
private final RestAssuredSnippetConfigurer snippetConfigurer = new RestAssuredSnippetConfigurer(
|
||||
this);
|
||||
|
||||
private final List<AbstractConfigurer> configurers;
|
||||
|
||||
private final RestDocumentation restDocumentation;
|
||||
|
||||
RestAssuredRestDocumentationConfigurer(RestDocumentation restDocumentation) {
|
||||
this.restDocumentation = restDocumentation;
|
||||
this.configurers = Arrays.asList(getTemplateEngineConfigurer(),
|
||||
getWriterResolverConfigurer(), snippets());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestAssuredSnippetConfigurer snippets() {
|
||||
return this.snippetConfigurer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response filter(FilterableRequestSpecification requestSpec,
|
||||
FilterableResponseSpecification responseSpec, FilterContext filterContext) {
|
||||
RestDocumentationContext context = this.restDocumentation.beforeOperation();
|
||||
filterContext.setValue(RestDocumentationContext.class.getName(), context);
|
||||
Map<String, Object> configuration = new HashMap<>();
|
||||
filterContext.setValue("org.springframework.restdocs.configuration",
|
||||
configuration);
|
||||
for (AbstractConfigurer configurer : this.configurers) {
|
||||
configurer.apply(configuration, context);
|
||||
}
|
||||
return filterContext.next(requestSpec, responseSpec);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import org.springframework.restdocs.config.SnippetConfigurer;
|
||||
|
||||
import com.jayway.restassured.filter.Filter;
|
||||
import com.jayway.restassured.filter.FilterContext;
|
||||
import com.jayway.restassured.response.Response;
|
||||
import com.jayway.restassured.specification.FilterableRequestSpecification;
|
||||
import com.jayway.restassured.specification.FilterableResponseSpecification;
|
||||
|
||||
/**
|
||||
* A configurer that can be used to configure the generated documentation snippets when
|
||||
* using REST Assured.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public final class RestAssuredSnippetConfigurer
|
||||
extends
|
||||
SnippetConfigurer<RestAssuredRestDocumentationConfigurer, RestAssuredSnippetConfigurer>
|
||||
implements Filter {
|
||||
|
||||
RestAssuredSnippetConfigurer(RestAssuredRestDocumentationConfigurer parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response filter(FilterableRequestSpecification requestSpec,
|
||||
FilterableResponseSpecification responseSpec, FilterContext context) {
|
||||
return and().filter(requestSpec, responseSpec, context);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.restdocs.RestDocumentationContext;
|
||||
import org.springframework.restdocs.config.SnippetConfigurer;
|
||||
import org.springframework.restdocs.operation.Operation;
|
||||
import org.springframework.restdocs.operation.OperationRequest;
|
||||
import org.springframework.restdocs.operation.OperationResponse;
|
||||
import org.springframework.restdocs.operation.StandardOperation;
|
||||
import org.springframework.restdocs.operation.preprocess.OperationRequestPreprocessor;
|
||||
import org.springframework.restdocs.operation.preprocess.OperationResponsePreprocessor;
|
||||
import org.springframework.restdocs.snippet.Snippet;
|
||||
|
||||
import com.jayway.restassured.filter.Filter;
|
||||
import com.jayway.restassured.filter.FilterContext;
|
||||
import com.jayway.restassured.response.Response;
|
||||
import com.jayway.restassured.specification.FilterableRequestSpecification;
|
||||
import com.jayway.restassured.specification.FilterableResponseSpecification;
|
||||
|
||||
/**
|
||||
* A REST Assured {@link Filter} for documenting RESTful APIs.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public final class RestDocumentationFilter implements Filter {
|
||||
|
||||
private final String identifier;
|
||||
|
||||
private final OperationRequestPreprocessor requestPreprocessor;
|
||||
|
||||
private final OperationResponsePreprocessor responsePreprocessor;
|
||||
|
||||
private final List<Snippet> snippets;
|
||||
|
||||
RestDocumentationFilter(String identifier, Snippet... snippets) {
|
||||
this(identifier, new IdentityOperationRequestPreprocessor(),
|
||||
new IdentityOperationResponsePreprocessor(), snippets);
|
||||
}
|
||||
|
||||
RestDocumentationFilter(String identifier,
|
||||
OperationRequestPreprocessor operationRequestPreprocessor,
|
||||
Snippet... snippets) {
|
||||
this(identifier, operationRequestPreprocessor,
|
||||
new IdentityOperationResponsePreprocessor(), snippets);
|
||||
}
|
||||
|
||||
RestDocumentationFilter(String identifier,
|
||||
OperationResponsePreprocessor operationResponsePreprocessor,
|
||||
Snippet... snippets) {
|
||||
this(identifier, new IdentityOperationRequestPreprocessor(),
|
||||
operationResponsePreprocessor, snippets);
|
||||
}
|
||||
|
||||
RestDocumentationFilter(String identifier,
|
||||
OperationRequestPreprocessor requestPreprocessor,
|
||||
OperationResponsePreprocessor responsePreprocessor, Snippet... snippets) {
|
||||
this.identifier = identifier;
|
||||
this.requestPreprocessor = requestPreprocessor;
|
||||
this.responsePreprocessor = responsePreprocessor;
|
||||
this.snippets = new ArrayList<>(Arrays.asList(snippets));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response filter(FilterableRequestSpecification requestSpec,
|
||||
FilterableResponseSpecification responseSpec, FilterContext context) {
|
||||
Response response = context.next(requestSpec, responseSpec);
|
||||
|
||||
OperationRequest operationRequest = this.requestPreprocessor
|
||||
.preprocess(new RestAssuredOperationRequestFactory()
|
||||
.createOperationRequest(requestSpec));
|
||||
OperationResponse operationResponse = this.responsePreprocessor
|
||||
.preprocess(new RestAssuredOperationResponseFactory()
|
||||
.createOperationResponse(response));
|
||||
|
||||
RestDocumentationContext documentationContext = context
|
||||
.getValue(RestDocumentationContext.class.getName());
|
||||
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(RestDocumentationContext.class.getName(), documentationContext);
|
||||
attributes.put("org.springframework.restdocs.urlTemplate",
|
||||
requestSpec.getUserDefinedPath());
|
||||
Map<String, Object> configuration = context
|
||||
.getValue("org.springframework.restdocs.configuration");
|
||||
attributes.putAll(configuration);
|
||||
|
||||
Operation operation = new StandardOperation(this.identifier, operationRequest,
|
||||
operationResponse, attributes);
|
||||
|
||||
try {
|
||||
for (Snippet snippet : getSnippets(configuration)) {
|
||||
snippet.document(operation);
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given {@code snippets} such that they are documented when this result
|
||||
* handler is called.
|
||||
*
|
||||
* @param snippets the snippets to add
|
||||
* @return this {@code RestDocumentationFilter}
|
||||
*/
|
||||
public RestDocumentationFilter snippets(Snippet... snippets) {
|
||||
this.snippets.addAll(Arrays.asList(snippets));
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<Snippet> getSnippets(Map<String, Object> configuration) {
|
||||
List<Snippet> combinedSnippets = new ArrayList<>(
|
||||
(List<Snippet>) configuration
|
||||
.get(SnippetConfigurer.ATTRIBUTE_DEFAULT_SNIPPETS));
|
||||
combinedSnippets.addAll(this.snippets);
|
||||
return combinedSnippets;
|
||||
}
|
||||
|
||||
private static final class IdentityOperationRequestPreprocessor implements
|
||||
OperationRequestPreprocessor {
|
||||
|
||||
@Override
|
||||
public OperationRequest preprocess(OperationRequest request) {
|
||||
return request;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class IdentityOperationResponsePreprocessor implements
|
||||
OperationResponsePreprocessor {
|
||||
|
||||
@Override
|
||||
public OperationResponse preprocess(OperationResponse response) {
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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.restassured.operation.preprocess;
|
||||
|
||||
import org.springframework.restdocs.operation.Operation;
|
||||
import org.springframework.restdocs.operation.OperationRequest;
|
||||
import org.springframework.restdocs.operation.OperationResponse;
|
||||
|
||||
/**
|
||||
* Static factory methods for creating
|
||||
* {@link org.springframework.restdocs.operation.preprocess.OperationPreprocessor
|
||||
* OperationPreprocessors} for use with REST Assured. They can be applied to an
|
||||
* {@link Operation Operation's} {@link OperationRequest request} or
|
||||
* {@link OperationResponse response} before it is documented.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public abstract class RestAssuredPreprocessors {
|
||||
|
||||
private RestAssuredPreprocessors() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code UriModifyingOperationPreprocessor} that will modify URIs in the
|
||||
* request or response by changing one or more of their host, scheme, and port.
|
||||
*
|
||||
* @return the preprocessor
|
||||
*/
|
||||
public static UriModifyingOperationPreprocessor modifyUris() {
|
||||
return new UriModifyingOperationPreprocessor();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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.restassured.operation.preprocess;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.operation.OperationRequest;
|
||||
import org.springframework.restdocs.operation.OperationRequestFactory;
|
||||
import org.springframework.restdocs.operation.OperationRequestPart;
|
||||
import org.springframework.restdocs.operation.OperationRequestPartFactory;
|
||||
import org.springframework.restdocs.operation.OperationResponse;
|
||||
import org.springframework.restdocs.operation.OperationResponseFactory;
|
||||
import org.springframework.restdocs.operation.preprocess.ContentModifier;
|
||||
import org.springframework.restdocs.operation.preprocess.ContentModifyingOperationPreprocessor;
|
||||
import org.springframework.restdocs.operation.preprocess.OperationPreprocessor;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* An {@link OperationPreprocessor} that modifies URIs in the request and in the response
|
||||
* by changing one or more of their host, scheme, and port. URIs in the following
|
||||
* locations are modified:
|
||||
* <ul>
|
||||
* <li>{@link OperationRequest#getUri() Request URI}
|
||||
* <li>{@link OperationRequest#getHeaders() Request headers}
|
||||
* <li>{@link OperationRequest#getContent() Request content}
|
||||
* <li>{@link OperationRequestPart#getHeaders() Request part headers}
|
||||
* <li>{@link OperationRequestPart#getContent() Request part content}
|
||||
* <li>{@link OperationResponse#getHeaders() Response headers}
|
||||
* <li>{@link OperationResponse#getContent() Response content}
|
||||
* </ul>
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public final class UriModifyingOperationPreprocessor implements OperationPreprocessor {
|
||||
|
||||
private final UriModifyingContentModifier contentModifier = new UriModifyingContentModifier();
|
||||
|
||||
private final OperationPreprocessor contentModifyingDelegate = new ContentModifyingOperationPreprocessor(
|
||||
this.contentModifier);
|
||||
|
||||
private String scheme;
|
||||
|
||||
private String host;
|
||||
|
||||
private String port;
|
||||
|
||||
/**
|
||||
* Modifies the URI to use the given {@code scheme}. {@code null}, the default, will
|
||||
* leave the scheme unchanged.
|
||||
*
|
||||
* @param scheme the scheme
|
||||
* @return {@code this}
|
||||
*/
|
||||
public UriModifyingOperationPreprocessor scheme(String scheme) {
|
||||
this.scheme = scheme;
|
||||
this.contentModifier.setScheme(scheme);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the URI to use the given {@code host}. {@code null}, the default, will
|
||||
* leave the host unchanged.
|
||||
*
|
||||
* @param host the host
|
||||
* @return {@code this}
|
||||
*/
|
||||
public UriModifyingOperationPreprocessor host(String host) {
|
||||
this.host = host;
|
||||
this.contentModifier.setHost(host);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the URI to use the given {@code port}.
|
||||
*
|
||||
* @param port the port
|
||||
* @return {@code this}
|
||||
*/
|
||||
public UriModifyingOperationPreprocessor port(int port) {
|
||||
return port(Integer.toString(port));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the port from the URI.
|
||||
*
|
||||
* @return {@code this}
|
||||
*/
|
||||
public UriModifyingOperationPreprocessor removePort() {
|
||||
return port("");
|
||||
}
|
||||
|
||||
private UriModifyingOperationPreprocessor port(String port) {
|
||||
this.port = port;
|
||||
this.contentModifier.setPort(port);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OperationRequest preprocess(OperationRequest request) {
|
||||
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUri(request.getUri());
|
||||
if (this.scheme != null) {
|
||||
uriBuilder.scheme(this.scheme);
|
||||
}
|
||||
if (this.host != null) {
|
||||
uriBuilder.host(this.host);
|
||||
}
|
||||
if (this.port != null) {
|
||||
if (StringUtils.hasText(this.port)) {
|
||||
uriBuilder.port(this.port);
|
||||
}
|
||||
else {
|
||||
uriBuilder.port(null);
|
||||
}
|
||||
}
|
||||
HttpHeaders modifiedHeaders = modify(request.getHeaders());
|
||||
if (this.host != null) {
|
||||
modifiedHeaders.set(HttpHeaders.HOST, this.host);
|
||||
}
|
||||
return this.contentModifyingDelegate.preprocess(new OperationRequestFactory()
|
||||
.create(uriBuilder.build().toUri(), request.getMethod(),
|
||||
request.getContent(), modifiedHeaders, request.getParameters(),
|
||||
modify(request.getParts())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public OperationResponse preprocess(OperationResponse response) {
|
||||
return this.contentModifyingDelegate.preprocess(new OperationResponseFactory()
|
||||
.create(response.getStatus(), modify(response.getHeaders()),
|
||||
response.getContent()));
|
||||
}
|
||||
|
||||
private HttpHeaders modify(HttpHeaders headers) {
|
||||
HttpHeaders modified = new HttpHeaders();
|
||||
for (Entry<String, List<String>> header : headers.entrySet()) {
|
||||
for (String value : header.getValue()) {
|
||||
modified.add(header.getKey(), this.contentModifier.modify(value));
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
private Collection<OperationRequestPart> modify(Collection<OperationRequestPart> parts) {
|
||||
List<OperationRequestPart> modifiedParts = new ArrayList<>();
|
||||
OperationRequestPartFactory factory = new OperationRequestPartFactory();
|
||||
for (OperationRequestPart part : parts) {
|
||||
modifiedParts.add(factory.create(part.getName(), part.getSubmittedFileName(),
|
||||
this.contentModifier.modifyContent(part.getContent(), part
|
||||
.getHeaders().getContentType()), modify(part.getHeaders())));
|
||||
}
|
||||
return modifiedParts;
|
||||
}
|
||||
|
||||
private static final class UriModifyingContentModifier implements ContentModifier {
|
||||
|
||||
private static final Pattern SCHEME_HOST_PORT_PATTERN = Pattern
|
||||
.compile("(http[s]?)://([^/:#?]+)(:[0-9]+)?");
|
||||
|
||||
private String scheme;
|
||||
|
||||
private String host;
|
||||
|
||||
private String port;
|
||||
|
||||
private void setScheme(String scheme) {
|
||||
this.scheme = scheme;
|
||||
}
|
||||
|
||||
private void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
private void setPort(String port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] modifyContent(byte[] content, MediaType contentType) {
|
||||
String input;
|
||||
if (contentType != null && contentType.getCharSet() != null) {
|
||||
input = new String(content, contentType.getCharSet());
|
||||
}
|
||||
else {
|
||||
input = new String(content);
|
||||
}
|
||||
|
||||
return modify(input).getBytes();
|
||||
}
|
||||
|
||||
private String modify(String input) {
|
||||
List<String> replacements = Arrays.asList(this.scheme, this.host,
|
||||
StringUtils.hasText(this.port) ? ":" + this.port : this.port);
|
||||
|
||||
int previous = 0;
|
||||
|
||||
Matcher matcher = SCHEME_HOST_PORT_PATTERN.matcher(input);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
while (matcher.find()) {
|
||||
for (int i = 1; i <= matcher.groupCount(); i++) {
|
||||
if (matcher.start(i) >= 0) {
|
||||
builder.append(input.substring(previous, matcher.start(i)));
|
||||
}
|
||||
if (matcher.start(i) >= 0) {
|
||||
previous = matcher.end(i);
|
||||
}
|
||||
builder.append(getReplacement(matcher.group(i),
|
||||
replacements.get(i - 1)));
|
||||
}
|
||||
}
|
||||
|
||||
if (previous < input.length()) {
|
||||
builder.append(input.substring(previous));
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private String getReplacement(String original, String candidate) {
|
||||
if (candidate != null) {
|
||||
return candidate;
|
||||
}
|
||||
if (original != null) {
|
||||
return original;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* REST Assured-specific support for preprocessing an operation prior to it being
|
||||
* documented.
|
||||
*/
|
||||
package org.springframework.restdocs.restassured.operation.preprocess;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Core classes for using Spring REST Docs with REST Assured.
|
||||
*/
|
||||
package org.springframework.restdocs.restassured;
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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.restassured;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.IntegrationTest;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.operation.OperationRequest;
|
||||
import org.springframework.restdocs.operation.OperationRequestPart;
|
||||
import org.springframework.restdocs.restassured.RestAssuredOperationRequestFactoryTests.TestApplication;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.jayway.restassured.RestAssured;
|
||||
import com.jayway.restassured.specification.FilterableRequestSpecification;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link RestAssuredOperationRequestFactory}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = TestApplication.class)
|
||||
@WebAppConfiguration
|
||||
@IntegrationTest("server.port=0")
|
||||
public class RestAssuredOperationRequestFactoryTests {
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private final RestAssuredOperationRequestFactory factory = new RestAssuredOperationRequestFactory();
|
||||
|
||||
@Value("${local.server.port}")
|
||||
private int port;
|
||||
|
||||
@Test
|
||||
public void requestUri() {
|
||||
RequestSpecification requestSpec = RestAssured.given().port(this.port);
|
||||
requestSpec.get("/foo/bar");
|
||||
OperationRequest request = this.factory
|
||||
.createOperationRequest((FilterableRequestSpecification) requestSpec);
|
||||
assertThat(request.getUri(),
|
||||
is(equalTo(URI.create("http://localhost:" + this.port + "/foo/bar"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestMethod() {
|
||||
RequestSpecification requestSpec = RestAssured.given().port(this.port);
|
||||
requestSpec.head("/foo/bar");
|
||||
OperationRequest request = this.factory
|
||||
.createOperationRequest((FilterableRequestSpecification) requestSpec);
|
||||
assertThat(request.getMethod(), is(equalTo(HttpMethod.HEAD)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryStringParameters() {
|
||||
RequestSpecification requestSpec = RestAssured.given().port(this.port)
|
||||
.queryParam("foo", "bar");
|
||||
requestSpec.get("/");
|
||||
OperationRequest request = this.factory
|
||||
.createOperationRequest((FilterableRequestSpecification) requestSpec);
|
||||
assertThat(request.getParameters().size(), is(1));
|
||||
assertThat(request.getParameters().get("foo"), is(equalTo(Arrays.asList("bar"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryStringFromUrlParameters() {
|
||||
RequestSpecification requestSpec = RestAssured.given().port(this.port);
|
||||
requestSpec.get("/?foo=bar");
|
||||
OperationRequest request = this.factory
|
||||
.createOperationRequest((FilterableRequestSpecification) requestSpec);
|
||||
assertThat(request.getParameters().size(), is(1));
|
||||
assertThat(request.getParameters().get("foo"), is(equalTo(Arrays.asList("bar"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formParameters() {
|
||||
RequestSpecification requestSpec = RestAssured.given().port(this.port)
|
||||
.formParameter("foo", "bar");
|
||||
requestSpec.get("/");
|
||||
OperationRequest request = this.factory
|
||||
.createOperationRequest((FilterableRequestSpecification) requestSpec);
|
||||
assertThat(request.getParameters().size(), is(1));
|
||||
assertThat(request.getParameters().get("foo"), is(equalTo(Arrays.asList("bar"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestParameters() {
|
||||
RequestSpecification requestSpec = RestAssured.given().port(this.port)
|
||||
.parameter("foo", "bar");
|
||||
requestSpec.get("/");
|
||||
OperationRequest request = this.factory
|
||||
.createOperationRequest((FilterableRequestSpecification) requestSpec);
|
||||
assertThat(request.getParameters().size(), is(1));
|
||||
assertThat(request.getParameters().get("foo"), is(equalTo(Arrays.asList("bar"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headers() {
|
||||
RequestSpecification requestSpec = RestAssured.given().port(this.port)
|
||||
.header("Foo", "bar");
|
||||
requestSpec.get("/");
|
||||
OperationRequest request = this.factory
|
||||
.createOperationRequest((FilterableRequestSpecification) requestSpec);
|
||||
assertThat(request.getHeaders().toString(), request.getHeaders().size(), is(3));
|
||||
assertThat(request.getHeaders().get("Foo"), is(equalTo(Arrays.asList("bar"))));
|
||||
assertThat(request.getHeaders().get("Accept"), is(equalTo(Arrays.asList("*/*"))));
|
||||
assertThat(request.getHeaders().get("Host"),
|
||||
is(equalTo(Arrays.asList("localhost"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipart() {
|
||||
RequestSpecification requestSpec = RestAssured.given().port(this.port)
|
||||
.multiPart("a", "a.txt", "alpha", null)
|
||||
.multiPart("b", new ObjectBody("bar"), "application/json");
|
||||
requestSpec.post().then().statusCode(200);
|
||||
OperationRequest request = this.factory
|
||||
.createOperationRequest((FilterableRequestSpecification) requestSpec);
|
||||
Collection<OperationRequestPart> parts = request.getParts();
|
||||
assertThat(parts.size(), is(2));
|
||||
Iterator<OperationRequestPart> iterator = parts.iterator();
|
||||
OperationRequestPart part = iterator.next();
|
||||
assertThat(part.getName(), is(equalTo("a")));
|
||||
assertThat(part.getSubmittedFileName(), is(equalTo("a.txt")));
|
||||
assertThat(part.getContentAsString(), is(equalTo("alpha")));
|
||||
assertThat(part.getHeaders().getContentType(), is(equalTo(MediaType.TEXT_PLAIN)));
|
||||
part = iterator.next();
|
||||
assertThat(part.getName(), is(equalTo("b")));
|
||||
assertThat(part.getSubmittedFileName(), is(equalTo("file")));
|
||||
assertThat(part.getContentAsString(), is(equalTo("{\"foo\":\"bar\"}")));
|
||||
assertThat(part.getHeaders().getContentType(),
|
||||
is(equalTo(MediaType.APPLICATION_JSON)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void byteArrayBody() {
|
||||
RequestSpecification requestSpec = RestAssured.given().body("body".getBytes())
|
||||
.port(this.port);
|
||||
requestSpec.post();
|
||||
this.factory.createOperationRequest((FilterableRequestSpecification) requestSpec);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stringBody() {
|
||||
RequestSpecification requestSpec = RestAssured.given().body("body")
|
||||
.port(this.port);
|
||||
requestSpec.post();
|
||||
OperationRequest request = this.factory
|
||||
.createOperationRequest((FilterableRequestSpecification) requestSpec);
|
||||
assertThat(request.getContentAsString(), is(equalTo("body")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void objectBody() {
|
||||
RequestSpecification requestSpec = RestAssured.given()
|
||||
.body(new ObjectBody("bar")).port(this.port);
|
||||
requestSpec.post();
|
||||
OperationRequest request = this.factory
|
||||
.createOperationRequest((FilterableRequestSpecification) requestSpec);
|
||||
assertThat(request.getContentAsString(), is(equalTo("{\"foo\":\"bar\"}")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamBodyIsNotSupported() {
|
||||
RequestSpecification requestSpec = RestAssured.given()
|
||||
.body(new ByteArrayInputStream(new byte[] { 1, 2, 3, 4 }))
|
||||
.port(this.port);
|
||||
requestSpec.post();
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Unsupported request content: java.io.ByteArrayInputStream"));
|
||||
this.factory.createOperationRequest((FilterableRequestSpecification) requestSpec);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileBodyIsNotSupported() {
|
||||
RequestSpecification requestSpec = RestAssured.given()
|
||||
.body(new File("src/test/resources/body.txt")).port(this.port);
|
||||
requestSpec.post();
|
||||
this.thrown.expectMessage(equalTo("Unsupported request content: java.io.File"));
|
||||
this.factory.createOperationRequest((FilterableRequestSpecification) requestSpec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimal test web application.
|
||||
*/
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@RestController
|
||||
static class TestApplication {
|
||||
|
||||
@RequestMapping("/")
|
||||
void handle() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sample object body to verify JSON serialization.
|
||||
*/
|
||||
static class ObjectBody {
|
||||
|
||||
private final String foo;
|
||||
|
||||
ObjectBody(String foo) {
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
public String getFoo() {
|
||||
return this.foo;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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.restassured;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.restdocs.snippet.WriterResolver;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
|
||||
import com.jayway.restassured.filter.FilterContext;
|
||||
import com.jayway.restassured.specification.FilterableRequestSpecification;
|
||||
import com.jayway.restassured.specification.FilterableResponseSpecification;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.hasEntry;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link RestAssuredRestDocumentationConfigurer}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RestAssuredRestDocumentationConfigurerTests {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation("build");
|
||||
|
||||
private final FilterableRequestSpecification requestSpec = mock(FilterableRequestSpecification.class);
|
||||
|
||||
private final FilterableResponseSpecification responseSpec = mock(FilterableResponseSpecification.class);
|
||||
|
||||
private final FilterContext filterContext = mock(FilterContext.class);
|
||||
|
||||
private final RestAssuredRestDocumentationConfigurer configurer = new RestAssuredRestDocumentationConfigurer(
|
||||
this.restDocumentation);
|
||||
|
||||
@Test
|
||||
public void nextFilterIsCalled() {
|
||||
this.configurer.filter(this.requestSpec, this.responseSpec, this.filterContext);
|
||||
verify(this.filterContext).setValue(
|
||||
eq("org.springframework.restdocs.configuration"), any(Map.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configurationIsAddedToTheContext() {
|
||||
this.configurer.filter(this.requestSpec, this.responseSpec, this.filterContext);
|
||||
@SuppressWarnings("rawtypes")
|
||||
ArgumentCaptor<Map> configurationCaptor = ArgumentCaptor.forClass(Map.class);
|
||||
verify(this.filterContext).setValue(
|
||||
eq("org.springframework.restdocs.configuration"),
|
||||
configurationCaptor.capture());
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> configuration = configurationCaptor.getValue();
|
||||
assertThat(
|
||||
configuration,
|
||||
hasEntry(equalTo(TemplateEngine.class.getName()),
|
||||
instanceOf(TemplateEngine.class)));
|
||||
assertThat(
|
||||
configuration,
|
||||
hasEntry(equalTo(WriterResolver.class.getName()),
|
||||
instanceOf(WriterResolver.class)));
|
||||
assertThat(
|
||||
configuration,
|
||||
hasEntry(equalTo("org.springframework.restdocs.defaultSnippets"),
|
||||
instanceOf(List.class)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.restassured;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.IntegrationTest;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.restdocs.hypermedia.Link;
|
||||
import org.springframework.restdocs.restassured.RestAssuredRestDocumentationIntegrationTests.TestApplication;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.jayway.restassured.builder.RequestSpecBuilder;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
|
||||
import static com.jayway.restassured.RestAssured.given;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
|
||||
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.maskLinks;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.removeHeaders;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.replacePattern;
|
||||
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.request.RequestDocumentation.parameterWithName;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.pathParameters;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration;
|
||||
import static org.springframework.restdocs.restassured.operation.preprocess.RestAssuredPreprocessors.modifyUris;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.codeBlock;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.httpRequest;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.httpResponse;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.snippet;
|
||||
|
||||
/**
|
||||
* Integration tests for using Spring REST Docs with REST Assured.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = TestApplication.class)
|
||||
@WebAppConfiguration
|
||||
@IntegrationTest("server.port=0")
|
||||
public class RestAssuredRestDocumentationIntegrationTests {
|
||||
|
||||
@Rule
|
||||
public RestDocumentation restDocumentation = new RestDocumentation(
|
||||
"build/generated-snippets");
|
||||
|
||||
@Value("${local.server.port}")
|
||||
private int port;
|
||||
|
||||
@Test
|
||||
public void defaultSnippetGeneration() {
|
||||
given().port(this.port)
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(document("default")).get("/").then().statusCode(200);
|
||||
assertExpectedSnippetFilesExist(new File("build/generated-snippets/default"),
|
||||
"http-request.adoc", "http-response.adoc", "curl-request.adoc");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void curlSnippetWithContent() throws Exception {
|
||||
String contentType = "text/plain; charset=UTF-8";
|
||||
given().port(this.port)
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(document("curl-snippet-with-content")).accept("application/json")
|
||||
.content("content").contentType(contentType).post("/").then()
|
||||
.statusCode(200);
|
||||
|
||||
assertThat(
|
||||
new File(
|
||||
"build/generated-snippets/curl-snippet-with-content/curl-request.adoc"),
|
||||
is(snippet().withContents(
|
||||
codeBlock("bash").content(
|
||||
"$ curl 'http://localhost:" + this.port + "/' -i "
|
||||
+ "-X POST -H 'Accept: application/json' "
|
||||
+ "-H 'Content-Type: " + contentType + "' "
|
||||
+ "-d 'content'"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void curlSnippetWithQueryStringOnPost() throws Exception {
|
||||
given().port(this.port)
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(document("curl-snippet-with-query-string"))
|
||||
.accept("application/json").param("foo", "bar").param("a", "alpha")
|
||||
.post("/?foo=bar").then().statusCode(200);
|
||||
String contentType = "application/x-www-form-urlencoded; charset=ISO-8859-1";
|
||||
assertThat(
|
||||
new File(
|
||||
"build/generated-snippets/curl-snippet-with-query-string/curl-request.adoc"),
|
||||
is(snippet().withContents(
|
||||
codeBlock("bash").content(
|
||||
"$ curl " + "'http://localhost:" + this.port
|
||||
+ "/?foo=bar' -i -X POST "
|
||||
+ "-H 'Accept: application/json' "
|
||||
+ "-H 'Content-Type: " + contentType + "' "
|
||||
+ "-d 'a=alpha'"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksSnippet() throws Exception {
|
||||
given().port(this.port)
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(document("links",
|
||||
links(linkWithRel("rel").description("The description"))))
|
||||
.accept("application/json").get("/").then().statusCode(200);
|
||||
assertExpectedSnippetFilesExist(new File("build/generated-snippets/links"),
|
||||
"http-request.adoc", "http-response.adoc", "curl-request.adoc",
|
||||
"links.adoc");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathParametersSnippet() throws Exception {
|
||||
given().port(this.port)
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(document(
|
||||
"path-parameters",
|
||||
pathParameters(parameterWithName("foo").description(
|
||||
"The description")))).accept("application/json")
|
||||
.get("/{foo}", "").then().statusCode(200);
|
||||
assertExpectedSnippetFilesExist(new File(
|
||||
"build/generated-snippets/path-parameters"), "http-request.adoc",
|
||||
"http-response.adoc", "curl-request.adoc", "path-parameters.adoc");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestParametersSnippet() throws Exception {
|
||||
given().port(this.port)
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(document(
|
||||
"request-parameters",
|
||||
requestParameters(parameterWithName("foo").description(
|
||||
"The description")))).accept("application/json")
|
||||
.param("foo", "bar").get("/").then().statusCode(200);
|
||||
assertExpectedSnippetFilesExist(new File(
|
||||
"build/generated-snippets/request-parameters"), "http-request.adoc",
|
||||
"http-response.adoc", "curl-request.adoc", "request-parameters.adoc");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestFieldsSnippet() throws Exception {
|
||||
given().port(this.port)
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(document("request-fields", requestFields(fieldWithPath("a")
|
||||
.description("The description")))).accept("application/json")
|
||||
.content("{\"a\":\"alpha\"}").post("/").then().statusCode(200);
|
||||
assertExpectedSnippetFilesExist(new File(
|
||||
"build/generated-snippets/request-fields"), "http-request.adoc",
|
||||
"http-response.adoc", "curl-request.adoc", "request-fields.adoc");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseFieldsSnippet() throws Exception {
|
||||
given().port(this.port)
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(document(
|
||||
"response-fields",
|
||||
responseFields(
|
||||
fieldWithPath("a").description("The description"),
|
||||
fieldWithPath("links").description(
|
||||
"Links to other resources"))))
|
||||
.accept("application/json").get("/").then().statusCode(200);
|
||||
|
||||
assertExpectedSnippetFilesExist(new File(
|
||||
"build/generated-snippets/response-fields"), "http-request.adoc",
|
||||
"http-response.adoc", "curl-request.adoc", "response-fields.adoc");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterizedOutputDirectory() throws Exception {
|
||||
given().port(this.port)
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(document("{method-name}")).get("/").then().statusCode(200);
|
||||
assertExpectedSnippetFilesExist(new File(
|
||||
"build/generated-snippets/parameterized-output-directory"),
|
||||
"http-request.adoc", "http-response.adoc", "curl-request.adoc");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiStep() throws Exception {
|
||||
RequestSpecification spec = new RequestSpecBuilder().setPort(this.port)
|
||||
.addFilter(documentationConfiguration(this.restDocumentation))
|
||||
.addFilter(document("{method-name}-{step}")).build();
|
||||
given(spec).get("/").then().statusCode(200);
|
||||
assertExpectedSnippetFilesExist(
|
||||
new File("build/generated-snippets/multi-step-1/"), "http-request.adoc",
|
||||
"http-response.adoc", "curl-request.adoc");
|
||||
given(spec).get("/").then().statusCode(200);
|
||||
assertExpectedSnippetFilesExist(
|
||||
new File("build/generated-snippets/multi-step-2/"), "http-request.adoc",
|
||||
"http-response.adoc", "curl-request.adoc");
|
||||
given(spec).get("/").then().statusCode(200);
|
||||
assertExpectedSnippetFilesExist(
|
||||
new File("build/generated-snippets/multi-step-3/"), "http-request.adoc",
|
||||
"http-response.adoc", "curl-request.adoc");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preprocessedRequest() throws Exception {
|
||||
Pattern pattern = Pattern.compile("(\"alpha\")");
|
||||
given().port(this.port)
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.header("a", "alpha")
|
||||
.header("b", "bravo")
|
||||
.contentType("application/json")
|
||||
.accept("application/json")
|
||||
.content("{\"a\":\"alpha\"}")
|
||||
.filter(document("original-request"))
|
||||
.filter(document(
|
||||
"preprocessed-request",
|
||||
preprocessRequest(
|
||||
prettyPrint(),
|
||||
removeHeaders("a", HttpHeaders.HOST,
|
||||
HttpHeaders.CONTENT_LENGTH),
|
||||
replacePattern(pattern, "\"<<beta>>\"")))).get("/")
|
||||
.then().statusCode(200);
|
||||
assertThat(
|
||||
new File("build/generated-snippets/original-request/http-request.adoc"),
|
||||
is(snippet()
|
||||
.withContents(
|
||||
httpRequest(RequestMethod.GET, "/")
|
||||
.header("a", "alpha")
|
||||
.header("b", "bravo")
|
||||
.header("Accept",
|
||||
MediaType.APPLICATION_JSON_VALUE)
|
||||
.header("Content-Type",
|
||||
"application/json; charset=UTF-8")
|
||||
.header("Host", "localhost")
|
||||
.header("Content-Length", "13")
|
||||
.content("{\"a\":\"alpha\"}"))));
|
||||
String prettyPrinted = String.format("{%n \"a\" : \"<<beta>>\"%n}");
|
||||
assertThat(
|
||||
new File(
|
||||
"build/generated-snippets/preprocessed-request/http-request.adoc"),
|
||||
is(snippet()
|
||||
.withContents(
|
||||
httpRequest(RequestMethod.GET, "/")
|
||||
.header("b", "bravo")
|
||||
.header("Accept",
|
||||
MediaType.APPLICATION_JSON_VALUE)
|
||||
.header("Content-Type",
|
||||
"application/json; charset=UTF-8")
|
||||
.content(prettyPrinted))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preprocessedResponse() throws Exception {
|
||||
Pattern pattern = Pattern.compile("(\"alpha\")");
|
||||
given().port(this.port)
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(document("original-response"))
|
||||
.filter(document(
|
||||
"preprocessed-response",
|
||||
preprocessResponse(
|
||||
prettyPrint(),
|
||||
maskLinks(),
|
||||
removeHeaders("a", "Transfer-Encoding", "Date", "Server"),
|
||||
replacePattern(pattern, "\"<<beta>>\""), modifyUris()
|
||||
.scheme("https").host("api.example.com")
|
||||
.removePort()))).get("/").then().statusCode(200);
|
||||
String prettyPrinted = String.format("{%n \"a\" : \"<<beta>>\",%n \"links\" : "
|
||||
+ "[ {%n \"rel\" : \"rel\",%n \"href\" : \"...\"%n } ]%n}");
|
||||
assertThat(
|
||||
new File(
|
||||
"build/generated-snippets/preprocessed-response/http-response.adoc"),
|
||||
is(snippet().withContents(
|
||||
httpResponse(HttpStatus.OK)
|
||||
.header("Foo", "https://api.example.com/foo/bar")
|
||||
.header("Content-Type", "application/json;charset=UTF-8")
|
||||
.header(HttpHeaders.CONTENT_LENGTH,
|
||||
prettyPrinted.getBytes().length)
|
||||
.content(prettyPrinted))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customSnippetTemplate() throws Exception {
|
||||
ClassLoader classLoader = new URLClassLoader(new URL[] { new File(
|
||||
"src/test/resources/custom-snippet-templates").toURI().toURL() },
|
||||
getClass().getClassLoader());
|
||||
ClassLoader previous = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(classLoader);
|
||||
try {
|
||||
given().port(this.port).accept("application/json")
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(document("custom-snippet-template")).get("/").then()
|
||||
.statusCode(200);
|
||||
}
|
||||
finally {
|
||||
Thread.currentThread().setContextClassLoader(previous);
|
||||
}
|
||||
assertThat(new File(
|
||||
"build/generated-snippets/custom-snippet-template/curl-request.adoc"),
|
||||
is(snippet().withContents(equalTo("Custom curl request"))));
|
||||
}
|
||||
|
||||
private void assertExpectedSnippetFilesExist(File directory, String... snippets) {
|
||||
for (String snippet : snippets) {
|
||||
File snippetFile = new File(directory, snippet);
|
||||
assertTrue("Snippet " + snippetFile + " not found", snippetFile.isFile());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimal test application called by the tests.
|
||||
*/
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@RestController
|
||||
static class TestApplication {
|
||||
|
||||
@RequestMapping(value = "/", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ResponseEntity<Map<String, Object>> foo() {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("a", "alpha");
|
||||
response.put("links", Arrays.asList(new Link("rel", "href")));
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add("a", "alpha");
|
||||
headers.add("Foo", "http://localhost:12345/foo/bar");
|
||||
return new ResponseEntity<>(response, headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/company/5", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public String bar() {
|
||||
return "{\"companyName\": \"FooBar\",\"employee\": [{\"name\": \"Lorem\",\"age\": \"42\"},{\"name\": \"Ipsum\",\"age\": \"24\"}]}";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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.restassured.operation.preprocess;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.restdocs.operation.OperationRequest;
|
||||
import org.springframework.restdocs.operation.OperationRequestFactory;
|
||||
import org.springframework.restdocs.operation.OperationRequestPart;
|
||||
import org.springframework.restdocs.operation.OperationRequestPartFactory;
|
||||
import org.springframework.restdocs.operation.OperationResponse;
|
||||
import org.springframework.restdocs.operation.OperationResponseFactory;
|
||||
import org.springframework.restdocs.operation.Parameters;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link UriModifyingOperationPreprocessor}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class UriModifyingOperationPreprocessorTests {
|
||||
|
||||
private final OperationRequestFactory requestFactory = new OperationRequestFactory();
|
||||
|
||||
private final OperationResponseFactory responseFactory = new OperationResponseFactory();
|
||||
|
||||
private final UriModifyingOperationPreprocessor preprocessor = new UriModifyingOperationPreprocessor();
|
||||
|
||||
@Test
|
||||
public void requestUriSchemeCanBeModified() {
|
||||
this.preprocessor.scheme("https");
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithUri("http://localhost:12345"));
|
||||
assertThat(processed.getUri(), is(equalTo(URI.create("https://localhost:12345"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUriHostCanBeModified() {
|
||||
this.preprocessor.host("api.example.com");
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithUri("http://api.example.com:12345"));
|
||||
assertThat(processed.getUri(),
|
||||
is(equalTo(URI.create("http://api.example.com:12345"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUriPortCanBeModified() {
|
||||
this.preprocessor.port(23456);
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithUri("http://api.example.com:12345"));
|
||||
assertThat(processed.getUri(),
|
||||
is(equalTo(URI.create("http://api.example.com:23456"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUriPortCanBeRemoved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithUri("http://api.example.com:12345"));
|
||||
assertThat(processed.getUri(), is(equalTo(URI.create("http://api.example.com"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUriPathIsPreserved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithUri("http://api.example.com:12345/foo/bar"));
|
||||
assertThat(processed.getUri(),
|
||||
is(equalTo(URI.create("http://api.example.com/foo/bar"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUriQueryIsPreserved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithUri("http://api.example.com:12345?foo=bar"));
|
||||
assertThat(processed.getUri(),
|
||||
is(equalTo(URI.create("http://api.example.com?foo=bar"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUriAnchorIsPreserved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithUri("http://api.example.com:12345#foo"));
|
||||
assertThat(processed.getUri(),
|
||||
is(equalTo(URI.create("http://api.example.com#foo"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestContentUriSchemeCanBeModified() {
|
||||
this.preprocessor.scheme("https");
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithContent("The uri 'http://localhost:12345' should be used"));
|
||||
assertThat(new String(processed.getContent()),
|
||||
is(equalTo("The uri 'https://localhost:12345' should be used")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestContentUriHostCanBeModified() {
|
||||
this.preprocessor.host("api.example.com");
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithContent("The uri 'http://localhost:12345' should be used"));
|
||||
assertThat(new String(processed.getContent()),
|
||||
is(equalTo("The uri 'http://api.example.com:12345' should be used")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestContentUriPortCanBeModified() {
|
||||
this.preprocessor.port(23456);
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithContent("The uri 'http://localhost:12345' should be used"));
|
||||
assertThat(new String(processed.getContent()),
|
||||
is(equalTo("The uri 'http://localhost:23456' should be used")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestContentUriPortCanBeRemoved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithContent("The uri 'http://localhost:12345' should be used"));
|
||||
assertThat(new String(processed.getContent()),
|
||||
is(equalTo("The uri 'http://localhost' should be used")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleRequestContentUrisCanBeModified() {
|
||||
this.preprocessor.removePort();
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithContent("Use 'http://localhost:12345' or 'https://localhost:23456' to access the service"));
|
||||
assertThat(
|
||||
new String(processed.getContent()),
|
||||
is(equalTo("Use 'http://localhost' or 'https://localhost' to access the service")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestContentUriPathIsPreserved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithContent("The uri 'http://localhost:12345/foo/bar' should be used"));
|
||||
assertThat(new String(processed.getContent()),
|
||||
is(equalTo("The uri 'http://localhost/foo/bar' should be used")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestContentUriQueryIsPreserved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithContent("The uri 'http://localhost:12345?foo=bar' should be used"));
|
||||
assertThat(new String(processed.getContent()),
|
||||
is(equalTo("The uri 'http://localhost?foo=bar' should be used")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestContentUriAnchorIsPreserved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithContent("The uri 'http://localhost:12345#foo' should be used"));
|
||||
assertThat(new String(processed.getContent()),
|
||||
is(equalTo("The uri 'http://localhost#foo' should be used")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseContentUriSchemeCanBeModified() {
|
||||
this.preprocessor.scheme("https");
|
||||
OperationResponse processed = this.preprocessor
|
||||
.preprocess(createResponseWithContent("The uri 'http://localhost:12345' should be used"));
|
||||
assertThat(new String(processed.getContent()),
|
||||
is(equalTo("The uri 'https://localhost:12345' should be used")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseContentUriHostCanBeModified() {
|
||||
this.preprocessor.host("api.example.com");
|
||||
OperationResponse processed = this.preprocessor
|
||||
.preprocess(createResponseWithContent("The uri 'http://localhost:12345' should be used"));
|
||||
assertThat(new String(processed.getContent()),
|
||||
is(equalTo("The uri 'http://api.example.com:12345' should be used")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseContentUriPortCanBeModified() {
|
||||
this.preprocessor.port(23456);
|
||||
OperationResponse processed = this.preprocessor
|
||||
.preprocess(createResponseWithContent("The uri 'http://localhost:12345' should be used"));
|
||||
assertThat(new String(processed.getContent()),
|
||||
is(equalTo("The uri 'http://localhost:23456' should be used")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseContentUriPortCanBeRemoved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationResponse processed = this.preprocessor
|
||||
.preprocess(createResponseWithContent("The uri 'http://localhost:12345' should be used"));
|
||||
assertThat(new String(processed.getContent()),
|
||||
is(equalTo("The uri 'http://localhost' should be used")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleResponseContentUrisCanBeModified() {
|
||||
this.preprocessor.removePort();
|
||||
OperationResponse processed = this.preprocessor
|
||||
.preprocess(createResponseWithContent("Use 'http://localhost:12345' or 'https://localhost:23456' to access the service"));
|
||||
assertThat(
|
||||
new String(processed.getContent()),
|
||||
is(equalTo("Use 'http://localhost' or 'https://localhost' to access the service")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseContentUriPathIsPreserved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationResponse processed = this.preprocessor
|
||||
.preprocess(createResponseWithContent("The uri 'http://localhost:12345/foo/bar' should be used"));
|
||||
assertThat(new String(processed.getContent()),
|
||||
is(equalTo("The uri 'http://localhost/foo/bar' should be used")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseContentUriQueryIsPreserved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationResponse processed = this.preprocessor
|
||||
.preprocess(createResponseWithContent("The uri 'http://localhost:12345?foo=bar' should be used"));
|
||||
assertThat(new String(processed.getContent()),
|
||||
is(equalTo("The uri 'http://localhost?foo=bar' should be used")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseContentUriAnchorIsPreserved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationResponse processed = this.preprocessor
|
||||
.preprocess(createResponseWithContent("The uri 'http://localhost:12345#foo' should be used"));
|
||||
assertThat(new String(processed.getContent()),
|
||||
is(equalTo("The uri 'http://localhost#foo' should be used")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urisInRequestHeadersCanBeModified() {
|
||||
OperationRequest processed = this.preprocessor.host("api.example.com")
|
||||
.preprocess(createRequestWithHeader("Foo", "http://locahost:12345"));
|
||||
assertThat(processed.getHeaders().getFirst("Foo"),
|
||||
is(equalTo("http://api.example.com:12345")));
|
||||
assertThat(processed.getHeaders().getFirst("Host"),
|
||||
is(equalTo("api.example.com")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urisInResponseHeadersCanBeModified() {
|
||||
OperationResponse processed = this.preprocessor.host("api.example.com")
|
||||
.preprocess(createResponseWithHeader("Foo", "http://locahost:12345"));
|
||||
assertThat(processed.getHeaders().getFirst("Foo"),
|
||||
is(equalTo("http://api.example.com:12345")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urisInRequestPartHeadersCanBeModified() {
|
||||
OperationRequest processed = this.preprocessor.host("api.example.com")
|
||||
.preprocess(
|
||||
createRequestWithPartWithHeader("Foo", "http://locahost:12345"));
|
||||
assertThat(processed.getParts().iterator().next().getHeaders().getFirst("Foo"),
|
||||
is(equalTo("http://api.example.com:12345")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urisInRequestPartContentCanBeModified() {
|
||||
OperationRequest processed = this.preprocessor
|
||||
.host("api.example.com")
|
||||
.preprocess(
|
||||
createRequestWithPartWithContent("The uri 'http://localhost:12345' should be used"));
|
||||
assertThat(new String(processed.getParts().iterator().next().getContent()),
|
||||
is(equalTo("The uri 'http://api.example.com:12345' should be used")));
|
||||
}
|
||||
|
||||
private OperationRequest createRequestWithUri(String uri) {
|
||||
return this.requestFactory.create(URI.create(uri), HttpMethod.GET, new byte[0],
|
||||
new HttpHeaders(), new Parameters(),
|
||||
Collections.<OperationRequestPart>emptyList());
|
||||
}
|
||||
|
||||
private OperationRequest createRequestWithContent(String content) {
|
||||
return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET,
|
||||
content.getBytes(), new HttpHeaders(), new Parameters(),
|
||||
Collections.<OperationRequestPart>emptyList());
|
||||
}
|
||||
|
||||
private OperationRequest createRequestWithHeader(String name, String value) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add(name, value);
|
||||
return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET,
|
||||
new byte[0], headers, new Parameters(),
|
||||
Collections.<OperationRequestPart>emptyList());
|
||||
}
|
||||
|
||||
private OperationRequest createRequestWithPartWithHeader(String name, String value) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add(name, value);
|
||||
return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET,
|
||||
new byte[0], new HttpHeaders(), new Parameters(), Arrays
|
||||
.asList(new OperationRequestPartFactory().create("part",
|
||||
"fileName", new byte[0], headers)));
|
||||
}
|
||||
|
||||
private OperationRequest createRequestWithPartWithContent(String content) {
|
||||
return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET,
|
||||
new byte[0], new HttpHeaders(), new Parameters(), Arrays
|
||||
.asList(new OperationRequestPartFactory().create("part",
|
||||
"fileName", content.getBytes(), new HttpHeaders())));
|
||||
}
|
||||
|
||||
private OperationResponse createResponseWithContent(String content) {
|
||||
return this.responseFactory.create(HttpStatus.OK, new HttpHeaders(),
|
||||
content.getBytes());
|
||||
}
|
||||
|
||||
private OperationResponse createResponseWithHeader(String name, String value) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add(name, value);
|
||||
return this.responseFactory.create(HttpStatus.OK, headers, new byte[0]);
|
||||
}
|
||||
|
||||
}
|
||||
1
spring-restdocs-restassured/src/test/resources/body.txt
Normal file
1
spring-restdocs-restassured/src/test/resources/body.txt
Normal file
@@ -0,0 +1 @@
|
||||
file
|
||||
@@ -0,0 +1 @@
|
||||
Custom curl request
|
||||
Reference in New Issue
Block a user