简介
通过将手写文档与 Spring MVC Test 生成的自动生成的片段结合起来,记录 RESTful 服务。
详细说就是,通过编写单元测试利用 asciidoctor 生成 adoc 文档,然后将这些 adoc 片段输出 HTML。
代码示例
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| <spring-restdocs.version>2.0.4.RELEASE</spring-restdocs.version>
<dependency> <groupId>org.springframework.restdocs</groupId> <artifactId>spring-restdocs-mockmvc</artifactId> <scope>test</scope> </dependency>
<plugin> <groupId>org.asciidoctor</groupId> <artifactId>asciidoctor-maven-plugin</artifactId> <version>1.5.8</version> <executions> <execution> <id>generate-docs</id> <phase>prepare-package</phase> <goals> <goal>process-asciidoc</goal> </goals> <configuration> <sourceDocumentName>index.adoc</sourceDocumentName> <backend>html</backend> <doctype>book</doctype> <attributes> <snippets>${project.build.directory}/generated-snippets</snippets> </attributes> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>org.springframework.restdocs</groupId> <artifactId>spring-restdocs-asciidoctor</artifactId> <version>${spring-restdocs.version}</version> </dependency> </dependencies> </plugin>
|
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| @SpringBootTest
@AutoConfigureMockMvc public class BusinessV2Test {
@Rule public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("target/generated-snippets"); @Autowired private WebApplicationContext context; public MockMvc mockMvc; @Before public void setup() { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context) .apply(documentationConfiguration(this.restDocumentation).uris().withScheme("https/http") .withHost("xxx/xxx").withPort(port)) .build(); } @Test public void xxx() { try { String example = "xxx"; MockHttpServletRequestBuilder builder = RestDocumentationRequestBuilders .post("接口").contentType(MediaType.APPLICATION_JSON_UTF8_VALUE) .accept(MediaType.APPLICATION_JSON_UTF8_VALUE).content(example); ResultActions perform = this.mockMvc.perform(builder); perform.andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcRestDocumentation.document("{ClassName}/{methodName}", Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), RequestDocumentation.requestParameters( RequestDocumentation.parameterWithName("xxx").description("xxx"), ), PayloadDocumentation.requestFields( PayloadDocumentation.fieldWithPath("xxx").description("xxx").optional(), ), PayloadDocumentation.responseFields( PayloadDocumentation.fieldWithPath("xxx").description("xxx"), ) )); } catch (Exception e) { e.printStackTrace(); } } }
|
捆绑测试(如果编写了多个测试类):
1 2 3 4
| @RunWith(Suite.class) @Suite.SuiteClasses({xxx.class, xxx.class}) public class ApplicationTests { }
|
index.adoc
固定写法:在 src/main 下加 asciidoc/index.adoc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| = -- 文件标题 :author: xxx :revnumber: xxx :revdate: 2020-04-23 :toc: left -- 文章目录,左浮动显示 :toc-title: -- 目录 :toclevels: 2 :iconsdir: ./icons -- 图标目录 ...
== 2. xxx -- 二级标题
[[xxx]] === xxx -- 三级标题
operation::index[snippets='curl-request,http-request,http-response']
等同于:
[[example_curl_request]] == Curl request 注: {snippets} 是 pom 那里配置的路径, index 是 MockMvcRestDocumentation.document 配置的路径 include::{snippets}/index/curl-request.adoc[]
[[example_http_request]] == HTTP request
include::{snippets}/index/http-request.adoc[]
[[example_http_response]] == HTTP response
include::{snippets}/index/http-response.adoc[]
|
总结
将 adoc 片段输出到指定目录
1 2
| @Rule public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("target/generated-snippets");
|
预期返回结果(200, 500...)
将 adoc 片段输出到指定目录下的子目录
例如下面这个就是输出到类名/方法名的目录下:
1
| perform.andDo(MockMvcRestDocumentation.document("{ClassName}/{methodName}"))
|
发送,携带一些请求头和请求参数或是请求体
1 2 3 4 5
| HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.add(HttpHeaders.AUTHORIZATION, "xxx"); httpHeaders.add(HttpHeaders.ACCEPT_LANGUAGE, "xxx"); RestDocumentationRequestBuilders.post("xxx").contentType(MediaType.APPLICATION_JSON_UTF8_VALUE).content(example).headers(httpHeaders)
|
将结果和请求打印
1 2
| Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), Preprocessors.preprocessResponse(Preprocessors.prettyPrint())
|
请求字段及描述,optional 是否必须
1 2 3
| PayloadDocumentation.requestFields( PayloadDocumentation.fieldWithPath("xxx").description("xxx").optional() )
|
响应字段
1 2 3
| PayloadDocumentation.responseFields( PayloadDocumentation.fieldWithPath("xxx").description("xxx") )
|
请求头
1 2 3
| HeaderDocumentation.requestHeaders( HeaderDocumentation.headerWithName("xxx").description("xxx") )
|
请求参数
1 2 3
| RequestDocumentation.requestParameters( RequestDocumentation.parameterWithName("xxx").description("xxx") )
|
捆绑测试(如果编写了多个测试类)
1 2
| @RunWith(Suite.class) @Suite.SuiteClasses({xxx.class, xxx.class})
|
针对对象属性的一些书写方式
参考:https://docs.spring.io/spring-restdocs/docs/1.2.6.RELEASE/reference/html5/#documenting-your-api-request-response-payloads-fields
Mockito + REST Docs 测试代码仓库地址