springboot~mockMvc和asciidoctor生成基於TDD的API文檔


API文檔是前端與后端快速開發,減少溝通成本的必要條件,有一份完善的文檔是很必要的,由通過測試來生成文檔的好處就是:測試數據有了,測試返回結果有了,而且可以對這些字段進行說明,很清晰,在springboot框架里,去使用mockMvc文檔生成時,需要有以下幾個步驟,大叔總結了一下,分享給大家。

一 mockMvc包引用

testCompile('org.springframework.restdocs:spring-restdocs-mockmvc')
asciidoctor 'org.springframework.restdocs:spring-restdocs-asciidoctor'

二 snippetsDir插件引用

在buildscript塊里添加如下代碼

maven {
url "https://plugins.gradle.org/m2/"
}
mavenCentral()
dependencies {
classpath "org.asciidoctor:asciidoctor-gradle-jvm:2.0.0-rc.1"

}

 添加插件

apply plugin: "org.asciidoctor.convert"

三 配置三大路徑的地址,三大路徑指,asciidoctor文檔路徑,生成的API文檔目錄和snippets目錄

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

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


integTest {
    outputs.dir snippetsDir
}

asciidoctor {
inputs.dir snippetsDir outputDir "build/asciidoc" dependsOn integTest sourceDir 'src/docs/asciidoc' }

四 添加API接口

@RestController
public class DocController {
  public static final String DOC = "/doc/{name}";
  public static final String DOC_LIST = "/doc/list";

  @GetMapping(DOC)
  public Map<String, String> index(@PathVariable String name) {
    Map<String, String> maps = new HashMap<>();
    maps.put("name", "Hello");
    maps.put("sex", "1");
    maps.put("buyer", name);
    return maps;
  }
}

五 添加測試用例

package test.lind.javaLindDay;

import static org.hamcrest.Matchers.containsString;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.relaxedRequestFields;
import static org.springframework.restdocs.payload.PayloadDocumentation.relaxedResponseFields;
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
import static org.springframework.restdocs.request.RequestDocumentation.pathParameters;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

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.context.SpringBootTest;
import org.springframework.restdocs.JUnitRestDocumentation;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
import org.springframework.restdocs.payload.RequestFieldsSnippet;
import org.springframework.restdocs.payload.ResponseFieldsSnippet;
import org.springframework.restdocs.request.PathParametersSnippet;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import test.lind.javaLindDay.controller.DocController;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("integTest")//指定profile環境
@RunWith(SpringRunner.class)
public class MockMvcTest {
  static final ResponseFieldsSnippet orderResponseFieldsParameters = relaxedResponseFields(
      fieldWithPath("name").description("賬號"),
      fieldWithPath("buyer").description("購買者"),
      fieldWithPath("sex").description("性別")
  );
  static final RequestFieldsSnippet orderRequestFieldsParameters = relaxedRequestFields(
      fieldWithPath("code").description("憑證號"),
      fieldWithPath("word").description("憑證字"),
      fieldWithPath("batch").description("批次")
  );
  static final PathParametersSnippet orderRequestPathParameters = pathParameters(
      parameterWithName("name").description("購買者")
  );

  @Rule
  public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();

  protected MockMvc mockMvc;

  @Autowired
  private WebApplicationContext context;

  @Before
  public void setUp() {
    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
        .apply(MockMvcRestDocumentation.documentationConfiguration(restDocumentation)
            .uris().withScheme("http").withHost("localhost").withPort(8080)
            .and()
            .operationPreprocessors().withResponseDefaults(prettyPrint()))
        .build();
  }


  @Test
  public void get_orders() throws Exception {
    this.mockMvc.perform(
        get(DocController.DOC, "zzl"))
        .andDo(print())
        .andExpect(status().isOk())
        .andExpect(content().string(containsString("Hello")))
        .andDo(document("doc-index", orderRequestPathParameters, orderResponseFieldsParameters));
  }

  @Test
  public void get_list() throws Exception {
    this.mockMvc.perform(
        get(DocController.DOC_LIST))
        .andDo(print())
        .andExpect(status().isOk())
        .andDo(document("doc-list", orderResponseFieldsParameters));
  }
}

這里有個需要注意的地址,get靜態方法的包應該是import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;否則會有找不到路由的

錯誤,這點困擾了我很久。

六 編譯,打包,它會同時去下載API DOC所需要的文件

gradle build

最后,進入build/asciidoc/html5目錄,瀏覽我們的API說明文件即可。

  

感謝各位的閱讀!

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM