Isolate and reduce Spring Test dependencies

This commit splits Spring REST Docs into two projects –
spring-restdocs-core and spring-restdocs-mockmvc.

spring-restdocs-core contains the vast majority of the code but does not
depend on a specific test framework other than JUnit. The use of a
Spring Test TestExecutionListener has been replaced with a JUnit test
rule. The rule is declared once per test class and configured with
the output directory to which the generated snippets should be written.
This simplifies the implementation as thread local storage is no longer
required to transfer information about the test that’s running into
Spring REST Docs. Instead, this transfer is now handled by the new test
rule. It has also simplified the configuration as it’s no longer
necessary for users to provide a system property that configures the
output directory.

spring-restdocs-mockmvc contains code that’s specific to using Spring
REST Docs with Spring MVC Test’s MockMvc. This is currently the only
testing framework that’s supported, but it paves the way for adding
support for additional frameworks. REST Assured is one that users seem
particularly interested in (see gh-80 and gh-102).

Closes gh-107
This commit is contained in:
Andy Wilkinson
2015-09-02 16:20:34 +01:00
parent 9d8bbf0558
commit 2b2b6fcd25
207 changed files with 1396 additions and 1425 deletions

View File

@@ -11,9 +11,33 @@ buildscript {
allprojects {
group = 'org.springframework.restdocs'
repositories {
jcenter()
}
}
apply plugin: 'samples'
apply plugin: 'sonar-runner'
sonarRunner {
sonarProperties {
property 'sonar.jacoco.reportPath', "${buildDir.name}/jacoco.exec"
property 'sonar.java.coveragePlugin', 'jacoco'
property 'sonar.links.ci', 'https://build.spring.io/browse/SRD'
property 'sonar.links.homepage', 'https://github.com/spring-projects/spring-restdocs'
property 'sonar.links.issue', 'https://github.com/spring-projects/spring-restdocs'
property 'sonar.links.scm', 'https://github.com/spring-projects/spring-restdocs'
}
}
ext {
springVersion = '4.1.7.RELEASE'
javadocLinks = [
'http://docs.oracle.com/javase/8/docs/api/',
"http://docs.spring.io/spring-framework/docs/$springVersion/javadoc-api/",
'https://docs.jboss.org/hibernate/stable/beanvalidation/api/'
] as String[]
}
subprojects {
apply plugin: 'io.spring.dependency-management'
@@ -22,10 +46,14 @@ subprojects {
apply plugin: 'propdeps'
apply plugin: 'propdeps-eclipse'
apply plugin: 'propdeps-maven'
apply plugin: 'maven'
sourceCompatibility = 1.7
targetCompatibility = 1.7
dependencyManagement {
imports {
mavenBom 'org.springframework:spring-framework-bom:4.1.7.RELEASE'
mavenBom "org.springframework:spring-framework-bom:$springVersion"
}
dependencies {
dependency 'com.fasterxml.jackson.core:jackson-databind:2.4.6'
@@ -41,10 +69,53 @@ subprojects {
dependency 'org.jacoco:org.jacoco.agent:0.7.2.201409121644'
}
}
configurations {
jacoco
}
dependencies {
jacoco 'org.jacoco:org.jacoco.agent::runtime'
}
test {
testLogging {
exceptionFormat "full"
}
}
javadoc {
description = "Generates project-level javadoc for use in -javadoc jar"
options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED
options.author = true
options.header = "Spring REST Docs $version"
options.docTitle = "${options.header} API"
options.links = javadocLinks
options.addStringOption '-quiet'
}
eclipseJdt.onlyIf { false }
cleanEclipseJdt.onlyIf { false }
task sourcesJar(type: Jar) {
classifier = 'sources'
from project.sourceSets.main.allSource
}
task javadocJar(type: Jar) {
classifier = "javadoc"
from javadoc
}
artifacts {
archives sourcesJar
archives javadocJar
}
}
samples {
dependOn 'spring-restdocs:install'
dependOn 'spring-restdocs-core:install'
dependOn 'spring-restdocs-mockmvc:install'
restNotesSpringHateoas {
workingDir 'samples/rest-notes-spring-hateoas'
@@ -55,18 +126,44 @@ samples {
}
}
task docsZip(type: Zip, dependsOn: [':docs:asciidoctor', ':spring-restdocs:javadoc']) {
task api (type: Javadoc) {
group = "Documentation"
description = "Generates aggregated Javadoc API documentation."
dependsOn {
subprojects.collect {
it.tasks.getByName("jar")
}
}
options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED
options.author = true
options.header = "Spring REST Docs $version"
options.splitIndex = true
options.links = javadocLinks
options.addStringOption '-quiet'
source subprojects.collect { project ->
project.sourceSets.main.allJava
}
destinationDir = new File(buildDir, "api")
doFirst {
classpath = files(subprojects.collect { it.sourceSets.main.compileClasspath })
}
}
task docsZip(type: Zip, dependsOn: [':docs:asciidoctor', ':api']) {
group = 'Distribution'
baseName = 'spring-restdocs'
classifier = 'docs'
description = 'Builds -${classifier} archive containing API and reference documentation'
description = "Builds -${classifier} archive containing API and reference documentation"
destinationDir = file("${project.buildDir}/distributions")
from(project.tasks.findByPath(':docs:asciidoctor')) {
into 'reference'
}
from (project.tasks.findByPath(':spring-restdocs:javadoc')) {
from(api) {
into 'api'
}
}

View File

@@ -37,14 +37,19 @@ public class SampleBuildConfigurer {
}
Task createTask(Project project, Object... dependencies) {
Task mavenBuild = mavenBuild(project, dependencies)
Task gradleBuild = gradleBuild(project, dependencies)
Task verifyIncludes = verifyIncludes(project)
verifyIncludes.dependsOn mavenBuild, gradleBuild
if (new File(this.workingDir, 'build.gradle').isFile()) {
Task gradleBuild = gradleBuild(project, dependencies)
verifyIncludes.dependsOn gradleBuild
}
if (new File(this.workingDir, 'pom.xml').isFile()) {
Task mavenBuild = mavenBuild(project, dependencies)
verifyIncludes.dependsOn(mavenBuild)
}
Task sampleBuild = project.tasks.create name
sampleBuild.description = "Builds the ${name} sample"
sampleBuild.group = "Build"
sampleBuild.dependsOn mavenBuild, gradleBuild, verifyIncludes
sampleBuild.dependsOn verifyIncludes
return sampleBuild
}

View File

@@ -3,12 +3,8 @@ plugins {
}
dependencies {
compile 'org.springframework:spring-webmvc'
testCompile project(':spring-restdocs')
testCompile project(':spring-restdocs-mockmvc')
testCompile 'javax.validation:validation-api'
testCompile 'junit:junit'
testCompile 'org.springframework:spring-test'
}
tasks.findByPath("artifactoryPublish")?.enabled = false

View File

@@ -65,23 +65,3 @@ by default:
----
include::{examples-dir}/com/example/CustomDefaultSnippetsConfiguration.java[tags=custom-default-snippets]
----
[[configuration-output-directory]]
=== Snippet output directory
As described in <<getting-started-build-configuration>> the snippet output directory is
configured in your `pom.xml` or `build.gradle` file. This configuration applies to builds
on the command line, but it may not apply when running your tests in your IDE. In the
absence of the property, Spring REST Docs will write the generated snippets to standard
out.
If you'd prefer that your IDE writes the snippets to disk you can use a file in
`src/test/resources` named `documentation.properties` to specify the output directory that
should be used:
[source,properties]
----
org.springframework.restdocs.outputDir: target/generated-snippets
----

View File

@@ -36,10 +36,9 @@ The first step in using Spring REST Docs is to configure your project's build.
[[getting-started-build-configuration-gradle]]
==== Gradle build configuration
Both {samples}[sample applications] contain `build.gradle` files that you may wish to
use as a reference. The key parts of the configuration are described below.
The {samples/rest-notes-spring-hateoas}[Spring HATEOAS sample] contains a `build.gradle`
file that you may wish to use as a reference. The key parts of the configuration are
described below.
[source,groovy,indent=0,subs="verbatim,attributes"]
----
@@ -48,7 +47,7 @@ use as a reference. The key parts of the configuration are described below.
}
dependencies { <2>
testCompile 'org.springframework.restdocs:spring-restdocs:{project-version}'
testCompile 'org.springframework.restdocs:spring-restdocs-mockmvc:{project-version}'
}
ext { <3>
@@ -56,24 +55,25 @@ use as a reference. The key parts of the configuration are described below.
}
test { <4>
systemProperty 'org.springframework.restdocs.outputDir', snippetsDir
outputs.dir snippetsDir
}
asciidoctor { <5>
attributes 'snippets': snippetsDir
inputs.dir snippetsDir
dependsOn test
attributes 'snippets': snippetsDir <6>
inputs.dir snippetsDir <7>
dependsOn test <8>
}
----
<1> Apply the Asciidoctor plugin.
<2> Add a dependency on spring-restdocs in the `testCompile` configuration.
<3> Configure a property to define the output location for generated snippets.
<4> Configure the `test` task with the `org.springframework.restdocs.outputDir` system
property. This property controls the location into which Spring REST Docs will write the
snippets that it generates.
<5> Configure the `asciidoctor` task and define an attribute named `snippets`. You can
then use this attribute when including the generated snippets in your documentation.
<4> Configure the `test` task to add the snippets directory as an output.
<5> Configure the `asciidoctor` task
<6> Define an attribute named `snippets` that can be used when including the generated
snippets in your documentation.
<7> Configure the snippets directory as an input.
<8> Make the task depend on the test task so that the tests are run before the
documentation is created.
[[getting-started-build-configuration-gradle-packaging-the-documentation]]
@@ -100,16 +100,15 @@ directory:
[[getting-started-build-configuration-maven]]
==== Maven build configuration
Both {samples}[sample applications] contain `pom.xml` files that you may wish to
use as a reference. The key parts of the configuration are described below.
The {samples/rest-notes-spring-data-rest}[Spring Data REST sample] contains a `pom.xml`
file that you may wish to use as a reference. The key parts of the configuration are
described below.
[source,xml,indent=0,subs="verbatim,attributes"]
----
<dependency> <1>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs</artifactId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<version>{project-version}</version>
<scope>test</scope>
</dependency>
@@ -127,11 +126,6 @@ use as a reference. The key parts of the configuration are described below.
<includes>
<include>**/*Documentation.java</include>
</includes>
<systemPropertyVariables>
<org.springframework.restdocs.outputDir>
${snippetsDirectory}
</org.springframework.restdocs.outputDir>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin> <4>
@@ -159,14 +153,12 @@ use as a reference. The key parts of the configuration are described below.
</build>
----
<1> Add a dependency on `spring-restdocs` in the `test` scope.
<1> Add a dependency on `spring-restdocs-mockmvc` in the `test` scope.
<2> Configure a property to define the output location for generated snippets.
<3> Configure the SureFire plugin with the `org.springframework.restdocs.outputDir` system
property. This property controls the location into which Spring REST Docs will write the
snippets that it generates. The plugin is also configured to include files whose names end
with `Documentation.java`.
<4> Configure the Asciidoctor plugin and define an attribute named `snippets`. You can
then use this attribute when including the generated snippets in your documentation.
<3> Add the SureFire plugin and configure it to include files whose names end with
`Documentation.java`.
<4> Add the Asciidoctor plugin and configure it to define an attribute named `snippets`
that can be used when including the generated snippets in your documentation.
<5> [[getting-started-build-configuration-maven-plugin-phase]] If you want to
<<getting-started-build-configuration-maven-packaging, package the documentation>> in your
project's jar you should use the `prepare-package` phase.
@@ -233,7 +225,8 @@ documentation snippets for the result's request and response.
[[getting-started-documentation-snippets-setup]]
==== Setting up Spring MVC test
The first step in generating documentation snippets is to provide an `@Before` method
The first step in generating documentation snippets is to declare a `public`
`RestDocumentation` that's annotated as a JUnit `@Rule` and to provide an `@Before` method
that creates a `MockMvc` instance:
[source,java,indent=0]
@@ -241,6 +234,10 @@ that creates a `MockMvc` instance:
include::{examples-dir}/com/example/ExampleApplicationTests.java[tags=mock-mvc-setup]
----
The `RestDocumentation` rule is configured with the output directory into which
generated snippets should be written. This output directory should match the snippets
directory that you have configured in your `build.gradle` or `pom.xml` file.
The `MockMvc` instance is configured using a `RestDocumentationConfigurer`. An instance
of this class can be obtained from the static `documentationConfiguration()` method on
`org.springframework.restdocs.RestDocumentation`. `RestDocumentationConfigurer` applies
@@ -259,13 +256,14 @@ service and document the request and response.
----
include::{examples-dir}/com/example/InvokeService.java[tags=invoke-service]
----
<1> Invoke the root (`/`) of the service an indicate that an `application/json` response
<1> Invoke the root (`/`) of the service and indicate that an `application/json` response
is required.
<2> Assert that the service is produced the expected response.
<2> Assert that the service produced the expected response.
<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 `RestDocumentationResultHandler`. An instance of this class can be obtained from the
static `document` method on `org.springframework.restdocs.RestDocumentation`.
static `document` method on
`org.springframework.restdocs.mockmvc.MockMvcRestDocumentation`.
By default, three snippets a written:

View File

@@ -16,25 +16,32 @@
package com.example;
import static org.springframework.restdocs.RestDocumentation.document;
import static org.springframework.restdocs.RestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
import org.junit.Before;
import org.junit.Rule;
import org.springframework.restdocs.RestDocumentation;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
public class AlwaysDo {
@Rule
public final RestDocumentation restDocumentation = new RestDocumentation("build");
private MockMvc mockMvc;
private WebApplicationContext context;
// tag::always-do[]
@Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(documentationConfiguration())
.apply(documentationConfiguration(this.restDocumentation))
.alwaysDo(document("{method-name}/{step}/"))
.build();
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2014-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example;
import java.util.List;

View File

@@ -1,16 +1,37 @@
/*
* Copyright 2014-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example;
import static org.springframework.restdocs.RestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.curl.CurlDocumentation.curlRequest;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
import org.junit.Before;
import org.junit.Rule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.restdocs.RestDocumentation;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
public class CustomDefaultSnippetsConfiguration {
@Rule
public final RestDocumentation restDocumentation = new RestDocumentation("build");
@Autowired
private WebApplicationContext context;
@@ -20,7 +41,7 @@ public class CustomDefaultSnippetsConfiguration {
public void setUp() {
// tag::custom-default-snippets[]
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(documentationConfiguration().snippets()
.apply(documentationConfiguration(this.restDocumentation).snippets()
.withDefaults(curlRequest()))
.build();
// end::custom-default-snippets[]

View File

@@ -16,16 +16,21 @@
package com.example;
import static org.springframework.restdocs.RestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
import org.junit.Before;
import org.junit.Rule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.restdocs.RestDocumentation;
import org.springframework.test.web.servlet.MockMvc;
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");
@Autowired
private WebApplicationContext context;
@@ -35,7 +40,7 @@ public class CustomEncoding {
public void setUp() {
// tag::custom-encoding[]
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(documentationConfiguration().snippets()
.apply(documentationConfiguration(this.restDocumentation).snippets()
.withEncoding("ISO-8859-1"))
.build();
// end::custom-encoding[]

View File

@@ -16,16 +16,21 @@
package com.example;
import static org.springframework.restdocs.RestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
import org.junit.Before;
import org.junit.Rule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.restdocs.RestDocumentation;
import org.springframework.test.web.servlet.MockMvc;
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");
@Autowired
private WebApplicationContext context;
@@ -35,7 +40,7 @@ public class CustomUriConfiguration {
public void setUp() {
// tag::custom-uri-configuration[]
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(documentationConfiguration().uris()
.apply(documentationConfiguration(this.restDocumentation).uris()
.withScheme("https")
.withHost("example.com")
.withPort(443))

View File

@@ -17,16 +17,21 @@
package com.example;
import org.junit.Before;
import org.junit.Rule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.restdocs.RestDocumentation;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.restdocs.RestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
public class ExampleApplicationTests {
// tag::mock-mvc-setup[]
@Rule
public final RestDocumentation restDocumentation = new RestDocumentation("build/generated-snippets");
@Autowired
private WebApplicationContext context;
@@ -35,7 +40,7 @@ public class ExampleApplicationTests {
@Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(documentationConfiguration())
.apply(documentationConfiguration(this.restDocumentation))
.build();
}
// end::mock-mvc-setup[]

View File

@@ -16,12 +16,12 @@
package com.example;
import static org.springframework.restdocs.RestDocumentation.document;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.halLinks;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;

View File

@@ -16,8 +16,8 @@
package com.example;
import static org.springframework.restdocs.RestDocumentation.document;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.springframework.http.MediaType;

View File

@@ -16,8 +16,8 @@
package com.example;
import static org.springframework.restdocs.RestDocumentation.document;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
import static org.springframework.restdocs.request.RequestDocumentation.pathParameters;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

View File

@@ -16,9 +16,9 @@
package com.example;
import static org.springframework.restdocs.RestDocumentation.document;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;

View File

@@ -16,13 +16,13 @@
package com.example;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
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;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.removeHeaders;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
import static org.springframework.restdocs.RestDocumentation.document;
import org.springframework.test.web.servlet.MockMvc;

View File

@@ -16,9 +16,9 @@
package com.example;
import static org.springframework.restdocs.RestDocumentation.document;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

View File

@@ -1,68 +0,0 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.2.5.RELEASE'
}
}
plugins {
id "org.asciidoctor.convert" version "1.5.2"
}
apply plugin: 'java'
apply plugin: 'spring-boot'
apply plugin: 'eclipse'
repositories {
mavenLocal()
maven { url 'https://repo.spring.io/snapshot' }
mavenCentral()
}
group = 'com.example'
sourceCompatibility = 1.7
targetCompatibility = 1.7
dependencies {
compile 'org.springframework.boot:spring-boot-starter-data-rest'
compile 'org.springframework.boot:spring-boot-starter-data-jpa'
runtime 'com.h2database:h2'
testCompile 'com.jayway.jsonpath:json-path'
testCompile 'org.springframework.boot:spring-boot-starter-test'
testCompile 'org.springframework.restdocs:spring-restdocs:1.0.0.BUILD-SNAPSHOT'
}
ext {
snippetsDir = file('build/generated-snippets')
}
test {
systemProperty 'org.springframework.restdocs.outputDir', snippetsDir
outputs.dir snippetsDir
}
asciidoctor {
sourceDir 'src/main/asciidoc' // Align with Maven's default location
attributes 'snippets': snippetsDir
inputs.dir snippetsDir
dependsOn test
}
jar {
dependsOn asciidoctor
from ("${asciidoctor.outputDir}/html5") {
into 'static/docs'
}
}
task wrapper(type: Wrapper) {
gradleVersion = '2.3'
}
eclipseJdt.onlyIf { false }
cleanEclipseJdt.onlyIf { false }

View File

@@ -1,6 +0,0 @@
#Thu Apr 16 12:33:42 BST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.3-bin.zip

View File

@@ -1,164 +0,0 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

View File

@@ -1,90 +0,0 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -18,7 +18,6 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.7</java.version>
<snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory>
</properties>
<dependencies>
@@ -49,7 +48,7 @@
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs</artifactId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<scope>test</scope>
</dependency>
@@ -68,9 +67,6 @@
<includes>
<include>**/*Documentation.java</include>
</includes>
<systemPropertyVariables>
<org.springframework.restdocs.outputDir>${snippetsDirectory}</org.springframework.restdocs.outputDir>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
@@ -88,7 +84,7 @@
<backend>html</backend>
<doctype>book</doctype>
<attributes>
<snippets>${snippetsDirectory}</snippets>
<snippets>${project.build.directory}/generated-snippets</snippets>
</attributes>
</configuration>
</execution>
@@ -96,7 +92,6 @@
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy-resources</id>

View File

@@ -18,16 +18,16 @@ package com.example.notes;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.springframework.restdocs.RestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.RestDocumentation.document;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.patch;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.patch;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -39,11 +39,13 @@ import java.util.Map;
import javax.servlet.RequestDispatcher;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.hateoas.MediaTypes;
import org.springframework.restdocs.RestDocumentation;
import org.springframework.restdocs.payload.JsonFieldType;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@@ -58,6 +60,9 @@ import com.fasterxml.jackson.databind.ObjectMapper;
@WebAppConfiguration
public class ApiDocumentation {
@Rule
public final RestDocumentation restDocumentation = new RestDocumentation("target/generated-snippets");
@Autowired
private NoteRepository noteRepository;
@@ -75,18 +80,7 @@ public class ApiDocumentation {
@Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(documentationConfiguration()).build();
this.mockMvc = MockMvcBuilders
.webAppContextSetup(this.context)
.apply(documentationConfiguration()
.uris()
.withScheme("https")
.withHost("localhost")
.withPort(8443)
.and().snippets()
.withEncoding("ISO-8859-1"))
.build();
.apply(documentationConfiguration(this.restDocumentation)).build();
}
@Test

View File

@@ -19,11 +19,11 @@ package com.example.notes;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.springframework.restdocs.RestDocumentation.document;
import static org.springframework.restdocs.RestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.patch;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.patch;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -34,11 +34,13 @@ import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.hateoas.MediaTypes;
import org.springframework.restdocs.RestDocumentation;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
@@ -55,6 +57,9 @@ import com.jayway.jsonpath.JsonPath;
@WebAppConfiguration
public class GettingStartedDocumentation {
@Rule
public final RestDocumentation restDocumentation = new RestDocumentation("target/generated-snippets");
@Autowired
private ObjectMapper objectMapper;
@@ -66,7 +71,7 @@ public class GettingStartedDocumentation {
@Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(documentationConfiguration())
.apply(documentationConfiguration(this.restDocumentation))
.alwaysDo(document("{method-name}/{step}/"))
.build();
}

View File

@@ -35,7 +35,7 @@ dependencies {
testCompile 'com.jayway.jsonpath:json-path'
testCompile 'org.springframework.boot:spring-boot-starter-test'
testCompile 'org.springframework.restdocs:spring-restdocs:1.0.0.BUILD-SNAPSHOT'
testCompile 'org.springframework.restdocs:spring-restdocs-mockmvc:1.0.0.BUILD-SNAPSHOT'
}
ext {
@@ -43,7 +43,6 @@ ext {
}
test {
systemProperty 'org.springframework.restdocs.outputDir', snippetsDir
outputs.dir snippetsDir
}
@@ -61,9 +60,5 @@ jar {
}
}
task wrapper(type: Wrapper) {
gradleVersion = '2.3'
}
eclipseJdt.onlyIf { false }
cleanEclipseJdt.onlyIf { false }

View File

@@ -1,137 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>rest-notes-spring-hateoas</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.5.RELEASE</version>
<relativePath />
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.7</java.version>
<snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.atteo</groupId>
<artifactId>evo-inflector</artifactId>
<version>1.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/*Documentation.java</include>
</includes>
<systemPropertyVariables>
<org.springframework.restdocs.outputDir>${snippetsDirectory}</org.springframework.restdocs.outputDir>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>1.5.2</version>
<executions>
<execution>
<id>generate-docs</id>
<phase>prepare-package</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>html</backend>
<doctype>book</doctype>
<attributes>
<snippets>${snippetsDirectory}</snippets>
</attributes>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.outputDirectory}/static/docs</outputDirectory>
<resources>
<resource>
<directory>${project.build.directory}/generated-docs</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</project>

View File

@@ -18,11 +18,11 @@ package com.example.notes;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.springframework.restdocs.RestDocumentation.document;
import static org.springframework.restdocs.RestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.patch;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.patch;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
@@ -40,11 +40,13 @@ import java.util.Map;
import javax.servlet.RequestDispatcher;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.hateoas.MediaTypes;
import org.springframework.restdocs.RestDocumentation;
import org.springframework.restdocs.constraints.ConstraintDescriptions;
import org.springframework.restdocs.payload.FieldDescriptor;
import org.springframework.restdocs.payload.JsonFieldType;
@@ -62,6 +64,9 @@ import com.fasterxml.jackson.databind.ObjectMapper;
@WebAppConfiguration
public class ApiDocumentation {
@Rule
public final RestDocumentation restDocumentation = new RestDocumentation("build/generated-snippets");
@Autowired
private NoteRepository noteRepository;
@@ -79,7 +84,7 @@ public class ApiDocumentation {
@Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(documentationConfiguration()).build();
.apply(documentationConfiguration(this.restDocumentation)).build();
}
@Test

View File

@@ -19,11 +19,11 @@ package com.example.notes;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.springframework.restdocs.RestDocumentation.document;
import static org.springframework.restdocs.RestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.patch;
import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.patch;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -34,11 +34,13 @@ import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.hateoas.MediaTypes;
import org.springframework.restdocs.RestDocumentation;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
@@ -55,6 +57,9 @@ import com.jayway.jsonpath.JsonPath;
@WebAppConfiguration
public class GettingStartedDocumentation {
@Rule
public final RestDocumentation restDocumentation = new RestDocumentation("build/generated-snippets");
@Autowired
private ObjectMapper objectMapper;
@@ -66,7 +71,7 @@ public class GettingStartedDocumentation {
@Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(documentationConfiguration())
.apply(documentationConfiguration(this.restDocumentation))
.alwaysDo(document("{method-name}/{step}/"))
.build();
}

View File

@@ -1,4 +1,5 @@
rootProject.name = 'spring-restdocs-build'
rootProject.name = 'spring-restdocs'
include 'docs'
include 'spring-restdocs'
include 'spring-restdocs-core'
include 'spring-restdocs-mockmvc'

View File

@@ -0,0 +1,59 @@
configurations {
jarjar
jmustache
testArtifacts.extendsFrom testRuntime
}
task jmustacheRepackJar(type: Jar) { repackJar ->
repackJar.baseName = "restdocs-jmustache-repack"
repackJar.version = dependencyManagement.managedVersions['com.samskivert:jmustache']
doLast() {
project.ant {
taskdef name: "jarjar", classname: "com.tonicsystems.jarjar.JarJarTask",
classpath: configurations.jarjar.asPath
jarjar(destfile: repackJar.archivePath) {
configurations.jmustache.each { originalJar ->
zipfileset(src: originalJar, includes: '**/*.class')
}
rule(pattern: 'com.samskivert.**', result: 'org.springframework.restdocs.@1')
}
}
}
}
dependencies {
compile 'com.fasterxml.jackson.core:jackson-databind'
compile 'junit:junit'
compile 'org.springframework:spring-webmvc'
compile 'javax.servlet:javax.servlet-api'
compile files(jmustacheRepackJar)
jarjar 'com.googlecode.jarjar:jarjar:1.3'
jmustache 'com.samskivert:jmustache@jar'
optional 'javax.validation:validation-api'
testCompile 'org.mockito:mockito-core'
testCompile 'org.hamcrest:hamcrest-core'
testCompile 'org.hamcrest:hamcrest-library'
testCompile 'org.hibernate:hibernate-validator'
testRuntime 'org.glassfish:javax.el:3.0.0'
}
jar {
dependsOn jmustacheRepackJar
from(zipTree(jmustacheRepackJar.archivePath)) {
include "org/springframework/restdocs/**"
}
}
task testJar(type: Jar) {
classifier "test"
from sourceSets.test.output
}
artifacts {
testArtifacts testJar
}
test {
jvmArgs "-javaagent:${configurations.jacoco.asPath}=destfile=${buildDir}/jacoco.exec,includes=org.springframework.restdocs.*,excludes=org.springframework.restdocs.mustache.*"
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright 2014-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.restdocs;
import java.io.File;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
/**
* A JUnit {@link TestRule} used to bootstrap the generation of REST documentation from
* JUnit tests.
*
* @author Andy Wilkinson
*
*/
public class RestDocumentation implements TestRule {
private final String outputDirectory;
private RestDocumentationContext context;
/**
* Creates a new {@code RestDocumentation} instance that will generate snippets to the
* given {@code outputDirectory}
*
* @param outputDirectory the output directory
*/
public RestDocumentation(String outputDirectory) {
this.outputDirectory = outputDirectory;
}
@Override
public Statement apply(final Statement base, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
Class<?> testClass = description.getTestClass();
String methodName = description.getMethodName();
RestDocumentation.this.context = new RestDocumentationContext(testClass,
methodName, new File(RestDocumentation.this.outputDirectory));
try {
base.evaluate();
}
finally {
RestDocumentation.this.context = null;
}
}
};
}
/**
* Notification that a RESTful operation that should be documented is about to be
* performed. Returns a {@link RestDocumentationContext} for the operation.
*
* @return the context for the operation
*/
public RestDocumentationContext beforeOperation() {
this.context.getAndIncrementStepCount();
return this.context;
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright 2014-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.restdocs;
import java.io.File;
import java.util.concurrent.atomic.AtomicInteger;
/**
* {@code RestDocumentationContext} encapsulates the context in which the documentation of
* a RESTful API is being performed.
*
* @author Andy Wilkinson
*/
public final class RestDocumentationContext {
private final AtomicInteger stepCount = new AtomicInteger(0);
private final Class<?> testClass;
private final String testMethodName;
private final File outputDirectory;
/**
* Creates a new {@code RestDocumentationContext} for a test on the given
* {@code testClass} with given {@code testMethodName} that will generate
* documentation to the given {@code outputDirectory}.
*
* @param testClass the class whose test is being executed
* @param testMethodName the name of the test method that is being executed
* @param outputDirectory the directory to which documentation should be written.
*/
public RestDocumentationContext(Class<?> testClass, String testMethodName,
File outputDirectory) {
this.testClass = testClass;
this.testMethodName = testMethodName;
this.outputDirectory = outputDirectory;
}
/**
* Returns the class whose tests are currently executing
*
* @return The test class
*/
public Class<?> getTestClass() {
return this.testClass;
}
/**
* Returns the name of the test method that is currently executing
*
* @return The name of the test method
*/
public String getTestMethodName() {
return this.testMethodName;
}
/**
* Returns the current step count and then increments it
*
* @return The step count prior to it being incremented
*/
int getAndIncrementStepCount() {
return this.stepCount.getAndIncrement();
}
/**
* Returns the current step count
*
* @return The current step count
*/
public int getStepCount() {
return this.stepCount.get();
}
/**
* Returns the output directory to which generated snippets should be written.
*
* @return the output directory
*/
public File getOutputDirectory() {
return this.outputDirectory;
}
}

View File

@@ -1,3 +1,19 @@
/*
* 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.hypermedia;
import java.io.IOException;

View File

@@ -0,0 +1,38 @@
/*
* 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.operation.preprocess;
import org.springframework.restdocs.operation.OperationResponse;
/**
* An {@code OperationRequestPreprocessor} is used to modify an {@code OperationRequest}
* prior to it being documented.
*
* @author Andy Wilkinson
*/
public interface OperationResponsePreprocessor {
/**
* Processes and potentially modifies the given {@code response} before it is
* documented.
*
* @param response the response
* @return the modified response
*/
OperationResponse preprocess(OperationResponse response);
}

View File

@@ -1,3 +1,19 @@
/*
* 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.payload;
import java.io.IOException;

View File

@@ -14,29 +14,23 @@
* limitations under the License.
*/
package org.springframework.restdocs.config;
package org.springframework.restdocs.payload;
import org.springframework.core.NamedInheritableThreadLocal;
/**
* Thrown to indicate that a failure has occurred during payload handling
*
* @author Andy Wilkinson
*
*/
@SuppressWarnings("serial")
class PayloadHandlingException extends RuntimeException {
final class RestDocumentationContextHolder {
private static final NamedInheritableThreadLocal<RestDocumentationContext> currentContext = new NamedInheritableThreadLocal<>(
"REST Documentation Context");
private RestDocumentationContextHolder() {
}
static RestDocumentationContext getCurrentContext() {
return currentContext.get();
}
static void setCurrentContext(RestDocumentationContext context) {
currentContext.set(context);
}
static void removeCurrentContext() {
currentContext.remove();
/**
* Creates a new {@code PayloadHandlingException} with the given cause
* @param cause the cause of the failure
*/
PayloadHandlingException(Throwable cause) {
super(cause);
}
}

View File

@@ -1,3 +1,19 @@
/*
* 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.snippet;
import java.util.HashMap;

View File

@@ -14,11 +14,12 @@
* limitations under the License.
*/
package org.springframework.restdocs.config;
package org.springframework.restdocs.snippet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.restdocs.RestDocumentationContext;
import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
/**
@@ -28,14 +29,14 @@ import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
* <li>{@code step} the {@link RestDocumentationContext#getStepCount() step current
* count}.
* <li>{@code methodName} - the name of the
* {@link RestDocumentationContext#getTestMethod() current test method} formatted using
* camelCase
* {@link RestDocumentationContext#getTestMethodName() current test method} formatted
* using camelCase
* <li>{@code method-name} - the name of the
* {@link RestDocumentationContext#getTestMethod() current test method} formatted using
* kebab-case
* {@link RestDocumentationContext#getTestMethodName() current test method} formatted
* using kebab-case
* <li>{@code method_name} - the name of the
* {@link RestDocumentationContext#getTestMethod() current test method} formatted using
* snake_case
* {@link RestDocumentationContext#getTestMethodName() current test method} formatted
* using snake_case
* </ul>
*
* @author Andy Wilkinson
@@ -62,13 +63,13 @@ public class RestDocumentationContextPlaceholderResolver implements PlaceholderR
return Integer.toString(this.context.getStepCount());
}
if ("methodName".equals(placeholderName)) {
return this.context.getTestMethod().getName();
return this.context.getTestMethodName();
}
if ("method-name".equals(placeholderName)) {
return camelCaseToDash(this.context.getTestMethod().getName());
return camelCaseToDash(this.context.getTestMethodName());
}
if ("method_name".equals(placeholderName)) {
return camelCaseToUnderscore(this.context.getTestMethod().getName());
return camelCaseToUnderscore(this.context.getTestMethodName());
}
return null;
}

Some files were not shown because too many files have changed in this diff Show More