使用Spring REST docs & JUnit 5創建API服務文檔

在前後端分離盛興的時代,REST API是前後端通信的必要途徑。一個好的REST API,不僅符合RESTful規範,還需要有一個高質量的API服務文檔。對於API服務文檔來講,難點不是創建文檔,而是如何更高效的維護文檔,讓文檔和代碼的變化保持同步。錯誤的API服務文檔,會讓使用者走入歧途,還不如沒有文檔的好。

Spring REST Docs

值得開心的是,在Spring全家桶中就用這樣的工具來滿足我們的要求。Spring REST Docs採用手寫文檔和自動生成片段相結合的方式來創建API文檔。Asciidoc是手寫文檔的格式,這種文檔格式在Spring全家桶中廣廣泛使用,Spring Reference document就是使用它生成的。

Spring REST Docs依據單元測試時所需的HTTP請求及其響應自動生成單元測試的文檔。

配置

我們都知道現在流行的Java項目管理工具有Maven和Gradle兩種。在Spring Framework的高級版本,將項目管理工具從Maven切換到了Gradle。因此,我們也採用Gradle來管理我們的項目。

build.gradle配置

buildscript {
   repositories {
       mavenCentral()
   }
   dependencies {
       classpath 'org.springframework.boot:spring-boot-gradle-plugin:2.1.8.RELEASE'
   }
}

plugins {
   id "org.asciidoctor.convert" version "1.5.9.2"
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'eclipse'
apply plugin: 'io.spring.dependency-management'

repositories {
   mavenLocal()
   maven { url 'https://repo.spring.io/libs-snapshot' }
   mavenCentral()
}


sourceCompatibility = 1.8
targetCompatibility = 1.8

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

ext['spring-restdocs.version'] = '2.0.5.BUILD-SNAPSHOT'

dependencies {
   asciidoctor 'org.springframework.restdocs:spring-restdocs-asciidoctor'

   compile 'org.springframework.boot:spring-boot-starter-web'

   testCompile('org.springframework.boot:spring-boot-starter-test') {
       exclude group: 'junit', module: 'junit;'
   }
   testCompile 'org.springframework.restdocs:spring-restdocs-mockmvc'
   testCompile 'org.junit.jupiter:junit-jupiter-api'
   testRuntime 'org.junit.jupiter:junit-jupiter-engine'
}

test {
   outputs.dir snippetsDir
   useJUnitPlatform()
}

asciidoctor {
   inputs.dir snippetsDir
   dependsOn test
}

bootJar {
   dependsOn asciidoctor
   from("${asciidoctor.outputDir}/html5") {
       into 'static/docs'
   }
}

eclipseJdt.onlyIf { false }
cleanEclipseJdt.onlyIf { false }



































































在這裏,我們的單元測試JUnit使用JUnit 5版本,它在Spring 5中得到了很好的支持。

像其他的Spring Boot項目一樣,我們需要創建一個Application。

package io.github.tinyking.spotlighs.restdocs;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
* RestdocsApplication.
*
* @author tinyking
* @version 1.0
* @since 2019/10/15
*/






@SpringBootApplication
public class RestdocsApplication {
   public static void main(String[] args) {
       SpringApplication.run(RestdocsApplication.class, args);
   }
}













創建一個簡單的Controller,用來做的HTTP API測試

package io.github.tinyking.spotlighs.restdocs;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* SampleController.
*
* @author tinyking
* @version 1.0
* @since 2019/10/15
*/






@RestController
public class SampleController {

   @GetMapping("/")
   public String index() {
       return "Hello, World";
   }
}















接下來,我們需要爲Application創建一個使用JUnit 5單元測試

package io.github.tinyking.spotlighs.restdocs;

import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.restdocs.RestDocumentationContextProvider;
import org.springframework.restdocs.RestDocumentationExtension;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

/**
* RestdocsApplicationTest.
*
* @author tinyking
* @version 1.0
* @since 2019/10/15
*/






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

   @Autowired
   private WebApplicationContext wac;

   private MockMvc mockMvc;

   @BeforeEach
   public void setup(RestDocumentationContextProvider restDocumentationContextProvider) {
       this.mockMvc = MockMvcBuilders.webAppContextSetup(wac)
               .apply(documentationConfiguration(restDocumentationContextProvider)).build();
   }

   @Test
   public void sample() throws Exception {
       this.mockMvc.perform(get("/"))
               .andExpect(status().isOk())
               .andDo(document("sample"));
   }
}












































手寫文檔

就像一開始說的,我們需要手寫文檔+自動生成來實現REST API服務文檔。上面所有的操作都是爲了自動生成片段,下面我們來創建一個手寫文檔。

spotlight-spring-restdocs/src/docs/asciidoc/index.adoc

= 基於JUnit5的Spring restdocs實例
tinyking;
:doctype: book
:icons: font
:source-highlighter: highlightjs

Http curl請求示例:

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

Http請求:

include::{snippets}/sample/http-request.adoc[]

Http響應:

include::{snippets}/sample/http-response.adoc[]


















這就是一個簡單的手寫+自動的文檔,裏面的curl-request.adoc、http-request.adoc、

http-response.adoc都是根據單元測試自動生成的。

生成API文檔

接下來我們通過命名來生成API文檔

gradle bootJar

執行完成後,可以找到build/asciidoc/html5/index.html ,直接在瀏覽器中打開,如下:

圖片

總結

通過使用Spring REST docs,可以讓我們快速的生成API服務文檔,基於單元測試可以確保API文檔和代碼保持一致。並且Spring REST Docs的方式不像Swagger,它不會***我們的業務代碼,保證我們代碼的整潔性。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章