快速开始

本节介绍如何开始使用 Spring REST Docs。spring-doc.cadn.net.cn

要求

Spring REST Docs 具有以下最低要求:spring-doc.cadn.net.cn

此外,spring-restdocs-restassured 模块需要 REST Assured 5.2。spring-doc.cadn.net.cn

构建配置

使用 Spring REST Docs 的第一步是配置项目的构建。 Spring HATEOASSpring Data REST 示例分别包含 build.gradlepom.xml,您可以将其用作参考。 配置的关键部分在以下列表中描述:spring-doc.cadn.net.cn

Maven
<dependency> (1)
	<groupId>org.springframework.restdocs</groupId>
	<artifactId>spring-restdocs-mockmvc</artifactId>
	<version>{project-version}</version>
	<scope>test</scope>
</dependency>

<build>
	<plugins>
		<plugin> (2)
			<groupId>org.asciidoctor</groupId>
			<artifactId>asciidoctor-maven-plugin</artifactId>
			<version>2.2.1</version>
			<executions>
				<execution>
					<id>generate-docs</id>
					<phase>prepare-package</phase> (3)
					<goals>
						<goal>process-asciidoc</goal>
					</goals>
					<configuration>
						<backend>html</backend>
						<doctype>book</doctype>
					</configuration>
				</execution>
			</executions>
			<dependencies>
				<dependency> (4)
					<groupId>org.springframework.restdocs</groupId>
					<artifactId>spring-restdocs-asciidoctor</artifactId>
					<version>{project-version}</version>
				</dependency>
			</dependencies>
		</plugin>
	</plugins>
</build>
1 test 作用域中添加对 spring-restdocs-mockmvc 的依赖。 如果您想使用 WebTestClient 或 REST Assured 而不是 MockMvc,请分别添加对 spring-restdocs-webtestclientspring-restdocs-restassured 的依赖。
2 添加 Asciidoctor 插件。
3 使用 prepare-package 可使文档包含在软件包中
4 spring-restdocs-asciidoctor 添加为 Asciidoctor 插件的依赖项。 这将自动配置 snippets 属性,以便在您的 .adoc 文件中指向 target/generated-snippets。 它还允许您使用 operation 块宏。
Gradle
plugins { (1)
	id "org.asciidoctor.jvm.convert" version "3.3.2"
}

configurations {
	asciidoctorExt (2)
}

dependencies {
	asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor:{project-version}' (3)
	testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc:{project-version}' (4)
}

ext { (5)
	snippetsDir = file('build/generated-snippets')
}

test { (6)
	outputs.dir snippetsDir
}

asciidoctor { (7)
	inputs.dir snippetsDir (8)
	configurations 'asciidoctorExt' (9)
	dependsOn test (10)
}
1 应用 Asciidoctor 插件。
2 为扩展 Asciidoctor 的依赖项声明 asciidoctorExt 配置。
3 asciidoctorExt 配置中添加对 spring-restdocs-asciidoctor 的依赖。 这将自动配置 snippets 属性,以便在您的 .adoc 文件中指向 build/generated-snippets。 它还允许您使用 operation 块宏。
4 testImplementation 配置中添加对 spring-restdocs-mockmvc 的依赖。 如果您想使用 WebTestClient 或 REST Assured 而不是 MockMvc,请分别添加对 spring-restdocs-webtestclientspring-restdocs-restassured 的依赖。
5 配置一个 snippetsDir 属性,用于定义生成代码片段的输出位置。
6 让 Gradle 知道运行 test 任务会将输出写入 snippetsDir。这是 增量构建 所必需的。
7 配置 asciidoctor 任务。
8 让 Gradle 意识到运行该任务将从 snippetsDir 读取输入。这对于 增量构建 是必需的。
9 配置使用 asciidoctorExt 配置来支持扩展。
10 让该任务依赖于 test 任务,以便在生成文档之前先运行测试。

打包文档

您可能希望将生成的文档打包到项目的 jar 文件中——例如,以便通过 Spring Boot 将其作为静态内容提供。 为此,请配置项目的构建,使其满足以下条件:spring-doc.cadn.net.cn

  1. 文档在构建 jar 包之前生成spring-doc.cadn.net.cn

  2. 生成的文档包含在 jar 文件中spring-doc.cadn.net.cn

以下列表展示了如何在 Maven 和 Gradle 中实现:spring-doc.cadn.net.cn

Maven
<plugin> (1)
	<groupId>org.asciidoctor</groupId>
	<artifactId>asciidoctor-maven-plugin</artifactId>
	<!-- … -->
</plugin>
<plugin> (2)
	<artifactId>maven-resources-plugin</artifactId>
	<executions>
		<execution>
			<id>copy-resources</id>
			<phase>prepare-package</phase>
			<goals>
				<goal>copy-resources</goal>
			</goals>
			<configuration> (3)
				<outputDirectory>
					${project.build.outputDirectory}/static/docs
				</outputDirectory>
				<resources>
					<resource>
						<directory>
							${project.build.directory}/generated-docs
						</directory>
					</resource>
				</resources>
			</configuration>
		</execution>
	</executions>
</plugin>
1 Asciidoctor 插件的现有声明。
2 资源插件必须在 Asciidoctor 插件之后声明,因为它们绑定到相同的阶段 (prepare-package),并且资源插件必须在 Asciidoctor 插件之后运行,以确保文档在复制之前已生成。 如果您未使用 Spring Boot 及其插件管理功能,请使用适当的 <version> 来声明该插件。
3 将生成的文档复制到构建输出的 static/docs 目录中,之后它将被包含在 jar 文件中。
Gradle
bootJar {
	dependsOn asciidoctor (1)
	from ("${asciidoctor.outputDir}") { (2)
		into 'static/docs'
	}
}
1 确保在构建 jar 之前已生成文档。
2 将生成的文档复制到 jar 的 static/docs 目录中。

生成文档片段

Spring REST Docs 使用 Spring MVC 的测试框架、Spring WebFlux 的WebTestClientREST Assured向您正在文档化的服务发起请求。 随后,它会为请求及相应的响应生成文档片段。spring-doc.cadn.net.cn

设置您的测试

测试的具体设置方式取决于您所使用的测试框架。 Spring REST Docs 为 JUnit 5 和 JUnit 4 提供了一流的支持。 推荐使用 JUnit 5。 其他框架(如 TestNG)也受支持,但需要稍多的配置工作。spring-doc.cadn.net.cn

设置您的 JUnit 5 测试

使用 JUnit 5 时,生成文档片段的第一步是将 RestDocumentationExtension 应用到您的测试类。 以下示例展示了如何操作:spring-doc.cadn.net.cn

@ExtendWith(RestDocumentationExtension.class)
public class JUnit5ExampleTests {

在测试典型的 Spring 应用程序时,您还应应用 SpringExtensionspring-doc.cadn.net.cn

@ExtendWith({RestDocumentationExtension.class, SpringExtension.class})
public class JUnit5ExampleTests {

RestDocumentationExtension 会根据您的项目构建工具自动配置输出目录:spring-doc.cadn.net.cn

构建工具 输出目录

Mavenspring-doc.cadn.net.cn

target/generated-snippetsspring-doc.cadn.net.cn

Gradlespring-doc.cadn.net.cn

build/generated-snippetsspring-doc.cadn.net.cn

如果您使用的是 JUnit 5.1,可以通过在测试类中将扩展注册为字段,并在创建时提供输出目录来覆盖默认设置。 以下示例展示了如何实现这一点:spring-doc.cadn.net.cn

public class JUnit5ExampleTests {

	@RegisterExtension
	final RestDocumentationExtension restDocumentation = new RestDocumentationExtension ("custom");

}

接下来,您必须提供一个 @BeforeEach 方法来配置 MockMvc、WebTestClient 或 REST Assured。 以下示例展示了如何实现:spring-doc.cadn.net.cn

MockMvc
private MockMvc mockMvc;

@BeforeEach
void setUp(WebApplicationContext webApplicationContext, RestDocumentationContextProvider restDocumentation) {
	this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
		.apply(documentationConfiguration(restDocumentation)) (1)
		.build();
}
1 MockMvc 实例是通过使用 MockMvcRestDocumentationConfigurer 进行配置的。 您可以从 org.springframework.restdocs.mockmvc.MockMvcRestDocumentation 上的静态 documentationConfiguration() 方法获取此类的实例。
WebTestClient
private WebTestClient webTestClient;

@BeforeEach
void setUp(ApplicationContext applicationContext, RestDocumentationContextProvider restDocumentation) {
	this.webTestClient = WebTestClient.bindToApplicationContext(applicationContext)
		.configureClient()
		.filter(documentationConfiguration(restDocumentation)) (1)
		.build();
}
1 WebTestClient 实例是通过添加一个 WebTestClientRestDocumentationConfigurer 作为 ExchangeFilterFunction 来配置的。 您可以从 org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation 上的静态 documentationConfiguration() 方法获取该类的实例。
REST Assured
private RequestSpecification spec;

@BeforeEach
void setUp(RestDocumentationContextProvider restDocumentation) {
	this.spec = new RequestSpecBuilder().addFilter(documentationConfiguration(restDocumentation)) (1)
		.build();
}
1 REST Assured 通过添加一个 RestAssuredRestDocumentationConfigurer 作为 Filter 来进行配置。 您可以从 org.springframework.restdocs.restassured 包中 RestAssuredRestDocumentation 类的静态 documentationConfiguration() 方法获取该类的实例。

该配置器应用了合理的默认值,并提供了用于自定义配置的 API。 请参阅 配置部分 以获取更多信息。spring-doc.cadn.net.cn

设置您的 JUnit 4 测试

使用 JUnit 4 时,生成文档片段的第一步是声明一个标注为 JUnit @Rulepublic JUnitRestDocumentation 字段。 以下示例展示了如何实现这一点:spring-doc.cadn.net.cn

@Rule
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();

默认情况下,JUnitRestDocumentation 规则会根据项目的构建工具自动配置输出目录:spring-doc.cadn.net.cn

构建工具 输出目录

Mavenspring-doc.cadn.net.cn

target/generated-snippetsspring-doc.cadn.net.cn

Gradlespring-doc.cadn.net.cn

build/generated-snippetsspring-doc.cadn.net.cn

您可以在创建 JUnitRestDocumentation 实例时提供输出目录,以覆盖默认设置。 以下示例展示了如何实现:spring-doc.cadn.net.cn

@Rule
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("custom");

接下来,您必须提供一个 @Before 方法来配置 MockMvc、WebTestClient 或 REST Assured。 以下示例展示了如何实现:spring-doc.cadn.net.cn

MockMvc
private MockMvc mockMvc;

@Autowired
private WebApplicationContext context;

@Before
public void setUp() {
	this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
		.apply(documentationConfiguration(this.restDocumentation)) (1)
		.build();
}
1 MockMvc 实例是通过使用 MockMvcRestDocumentationConfigurer 进行配置的。 您可以从 org.springframework.restdocs.mockmvc.MockMvcRestDocumentation 上的静态 documentationConfiguration() 方法获取此类的实例。
WebTestClient
private WebTestClient webTestClient;

@Autowired
private ApplicationContext context;

@Before
public void setUp() {
	this.webTestClient = WebTestClient.bindToApplicationContext(this.context)
		.configureClient()
		.filter(documentationConfiguration(this.restDocumentation)) (1)
		.build();
}
1 WebTestClient 实例是通过添加一个 WebTestclientRestDocumentationConfigurer 作为 ExchangeFilterFunction 来配置的。 您可以从 org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation 上的静态 documentationConfiguration() 方法获取该类的实例。
REST Assured
private RequestSpecification spec;

@Before
public void setUp() {
	this.spec = new RequestSpecBuilder().addFilter(documentationConfiguration(this.restDocumentation)) (1)
		.build();
}
1 REST Assured 通过添加一个 RestAssuredRestDocumentationConfigurer 作为 Filter 来进行配置。 您可以从 org.springframework.restdocs.restassured 包中 RestAssuredRestDocumentation 类的静态 documentationConfiguration() 方法获取该类的实例。

该配置器应用了合理的默认值,并提供了用于自定义配置的 API。 请参阅 配置部分 以获取更多信息。spring-doc.cadn.net.cn

在不使用 JUnit 的情况下设置测试

当不使用 JUnit 时的配置与使用时的配置大体相似。 本节介绍主要差异。 TestNG 示例也说明了该方法。spring-doc.cadn.net.cn

第一个区别是,您应该使用 ManualRestDocumentation 代替 JUnitRestDocumentation。 此外,您不需要 @Rule 注解。 以下示例展示了如何使用 ManualRestDocumentationspring-doc.cadn.net.cn

private ManualRestDocumentation restDocumentation = new ManualRestDocumentation();

其次,您必须在每个测试之前调用 ManualRestDocumentation.beforeTest(Class, String)。 您可以将其作为配置 MockMvc、WebTestClient 或 REST Assured 的方法的一部分来完成。 以下示例展示了如何执行此操作:spring-doc.cadn.net.cn

MockMvc
private MockMvc mockMvc;

@Autowired
private WebApplicationContext context;

@BeforeMethod
public void setUp(Method method) {
	this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
		.apply(documentationConfiguration(this.restDocumentation))
		.build();
	this.restDocumentation.beforeTest(getClass(), method.getName());
}
WebTestClient
private WebTestClient webTestClient;

@Autowired
private ApplicationContext context;

@BeforeMethod
public void setUp(Method method) {
	this.webTestClient = WebTestClient.bindToApplicationContext(this.context)
		.configureClient()
		.filter(documentationConfiguration(this.restDocumentation)) (1)
		.build();
	this.restDocumentation.beforeTest(getClass(), method.getName());
}
REST Assured
private RequestSpecification spec;

@BeforeMethod
public void setUp(Method method) {
	this.spec = new RequestSpecBuilder().addFilter(documentationConfiguration(this.restDocumentation)).build();
	this.restDocumentation.beforeTest(getClass(), method.getName());
}

最后,您必须在每个测试后调用 ManualRestDocumentation.afterTest。 以下示例展示了如何使用 TestNG 执行此操作:spring-doc.cadn.net.cn

@AfterMethod
public void tearDown() {
	this.restDocumentation.afterTest();
}

调用 RESTful 服务

现在您已经配置好了测试框架,可以使用它来调用 RESTful 服务并记录请求和响应。 以下示例展示了如何实现这一点:spring-doc.cadn.net.cn

MockMvc
this.mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON)) (1)
	.andExpect(status().isOk()) (2)
	.andDo(document("index")); (3)
1 调用服务的根(/),并指示需要 application/json 响应。
2 断言服务产生了预期的响应。
3 记录对服务的调用,将代码片段写入名为 index 的目录(该目录位于配置的输出目录之下)。 这些代码片段由 RestDocumentationResultHandler 生成。 您可以通过调用 org.springframework.restdocs.mockmvc.MockMvcRestDocumentation 上的静态 document 方法来获取该类的实例。
WebTestClient
this.webTestClient.get()
	.uri("/")
	.accept(MediaType.APPLICATION_JSON) (1)
	.exchange()
	.expectStatus()
	.isOk() (2)
	.expectBody()
	.consumeWith(document("index")); (3)
1 调用服务的根(/),并指示需要 application/json 响应。
2 断言服务产生了预期的响应。
3 记录对服务的调用,将代码片段写入名为 index 的目录(该目录位于配置的输出目录之下)。 这些代码片段由 ExchangeResultConsumer 写入。 您可以通过 org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation 上的静态 document 方法获取此类消费者。
REST Assured
RestAssured.given(this.spec) (1)
	.accept("application/json") (2)
	.filter(document("index")) (3)
	.when()
	.get("/") (4)
	.then()
	.assertThat()
	.statusCode(is(200)); (5)
1 应用已在 @Before 方法中初始化的规范。
2 指示需要 application/json 响应。
3 记录对服务的调用,将代码片段写入名为 index 的目录(该目录位于配置的输出目录之下)。 这些代码片段由 RestDocumentationFilter 生成。 您可以从 org.springframework.restdocs.restassured 包中 RestAssuredRestDocumentation 类的静态 document 方法获取该类的实例。
4 调用服务的根 (/)。
5 断言服务产生预期的响应。

默认情况下,会写入六个代码片段:spring-doc.cadn.net.cn

有关 Spring REST Docs 可生成的这些及其他代码片段的更多信息,请参阅 API 文档编写指南spring-doc.cadn.net.cn

使用代码片段

在使用生成的代码片段之前,您必须创建一个 .adoc 源文件。 您可以将该文件命名为任何名称,只要它具有 .adoc 后缀即可。 生成的 HTML 文件具有相同的名称,但带有 .html 后缀。 源文件和生成的 HTML 文件的默认位置取决于您是使用 Maven 还是 Gradle:spring-doc.cadn.net.cn

构建工具 源文件 生成的文件

Mavenspring-doc.cadn.net.cn

src/main/asciidoc/*.adocspring-doc.cadn.net.cn

target/generated-docs/*.htmlspring-doc.cadn.net.cn

Gradlespring-doc.cadn.net.cn

src/docs/asciidoc/*.adocspring-doc.cadn.net.cn

build/asciidoc/html5/*.htmlspring-doc.cadn.net.cn

然后,您可以使用 include 宏 将生成的代码片段包含在手动创建的 Asciidoc 文件(本节前面已描述)中。 您可以使用由 构建配置 中配置的 spring-restdocs-asciidoctor 自动设置的 snippets 属性来引用代码片段输出目录。 以下示例展示了如何操作:spring-doc.cadn.net.cn

include::{snippets}/index/curl-request.adoc[]