swagger와 유사하게 API를 자동으로 문서화할 수 있도록 도와줍니다.
swagger의 장점은 적용하기 쉽고, api 테스트 화면 제공이고
단점으로는 어노테이션을 추가, 동기화가 불일치할 수 있음
restdocs의 장점은 코드에 영향을 받지 않고 테스트가 성공 후 문서화가 되고
단점은 적용이 어려움
아래 사이트에서 관련 정보를 얻을 수 있습니다.
docs.spring.io/spring-restdocs/docs/current/reference/html5/
www.baeldung.com/spring-rest-docs
1. 의존성 추가
plugins {
id 'org.asciidoctor.convert' version "1.5.6" // (1)
}
dependencies {
asciidoctor 'org.springframework.restdocs:spring-restdocs-asciidoctor'
testCompile 'org.springframework.restdocs:spring-restdocs-mockmvc'
}
// restdocs
ext {
snippetsDir = file('build/generated-snippets')
}
test {
outputs.dir snippetsDir
}
asciidoctor {
inputs.dir snippetsDir
dependsOn test
}
bootJar {
dependsOn asciidoctor
from ("${asciidoctor.outputDir}/html5") {
into 'docs/asciidoc'
}
}
2. Restdocs 테스트
패키지 구성은 아래와 같습니다.
2-1. RestdocsController.java
package com.otrodevym.spring.base.common.restdocs;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/restdocs")
public class RestdocsController {
@GetMapping("/hello/{name}")
public ResponseEntity<RestdocsTest> hello(@PathVariable String name) {
return ResponseEntity.ok().body(new RestdocsTest(name, "안녕!"));
}
}
2-2. RestdocsTest.java
package com.otrodevym.spring.base.common.restdocs;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class RestdocsTest {
private String name;
private String message;
@Builder
public RestdocsTest(String name, String message) {
this.name = name;
this.message = message;
}
}
2-3. Postman 테스트
localhost:9090/restdocs/hello/otrodevym
3. 테스트 및 문서화
3-1. BaseApplicationTests.java
기본적인 테스트 소스를 작성합니다.
.andDo(document("index"));가 테스트 코드를 만드는 소스입니다.
package com.otrodevym.spring.base;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.restdocs.ManualRestDocumentation;
import org.springframework.restdocs.RestDocumentationContextProvider;
import org.springframework.restdocs.RestDocumentationExtension;
import org.springframework.test.context.event.annotation.AfterTestMethod;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MockMvcBuilder;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.testng.annotations.AfterMethod;
import java.lang.reflect.Method;
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.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@ExtendWith({RestDocumentationExtension.class, SpringExtension.class})
class BaseApplicationTests {
@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
@Test
void contextLoads() {
}
@BeforeEach
public void setUp(RestDocumentationContextProvider restDocumentation) {
this.mockMvc =
MockMvcBuilders
.webAppContextSetup(this.webApplicationContext)
.apply(documentationConfiguration(restDocumentation))
.build();
}
@AfterMethod
public void tearDown() {
// this.restDocumentation.afterTest();
}
@Test
public void restTest() {
try {
this.mockMvc.perform(get("/hello/test").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(document("index"));
} catch (Exception e) {
e.printStackTrace();
}
// try {
// this.mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(document("index"));
// } catch (Exception e) {
// e.printStackTrace();
// }
// given
// String name = "otrodevym";
//
// // when
// try {
// mockMvc.perform(get("/hello/" + name)
// .characterEncoding("utf-8")
// .accept(MediaType.APPLICATION_JSON))
// .andExpect(status().isOk()) // then
// .andExpect(jsonPath("$.name").value(name))
// .andDo(document("hello")); // (3)
// } catch (Exception e) {
// e.printStackTrace();
// }
}
}
3-2. generated-snippets/index/*.adoc과 통합 adoc 파일 설정
3-2-1..adoc으로 끝나는 파일들이 생깁니다.
파일을 열어보면 소스 및 미리보기를 확인할 수 있습니다.
adoc 문서 작성 방법
아래 사이트에서 사용 방법을 확인할 수 있습니다.
https://docs.asciidoctor.org/home/
https://asciidoctor.org/docs/
3-2-2. adoc 통합 관리 파일 생성
adoc 파일들을 통합 관리 할 수 있는 adoc 파일을 생성합니다.
이 부분은 기존에 gradle에서 설정하는 내용과 일치해야 합나다.
아래 소스 코드를 입력하면 원하는 위치에서 adoc 파일들을 가져올 수 있습니다.
ifndef::snippets[]
:snippets: ../../../build/generated-snippets
endif::[]
== User App API
=== API 문서 자동생성
CURL:
include::{snippets}/index/curl-request.adoc[]
파일의 위치를 찾지 못하는 경우 다시 찾아주는 역할을 합니다.
ifndef::snippets[]
:snippets: ../../../build/generated-snippets
endif::[]
원하는 파일을 가져와 문서화를 합니다.
CURL:
include::{snippets}/index/curl-request.adoc[]
CURL:
include::{snippets}/hello/curl-request.adoc[]
Request Parameters:
include::{snippets}/hello/http-request.adoc[]
Request HTTP Example:
include::{snippets}/hello/http-request.adoc[]
=== Response
Response:
include::{snippets}/hello/http-response.adoc[]
3-3. index.html 파일 생성
이제 gradle을 빌드하면 /build/asciidoc/html/index.html 파일이 생성됩니다.
아래와 같이 확인할 수 있습니다.
'개발(합니다) > Java&Spring' 카테고리의 다른 글
[spring boot 설정하기-9] oauth2 설정 및 테스트 소스 (1) | 2021.04.23 |
---|---|
[spring boot 설정하기-8] security 설정 및 테스트 소스 (1) | 2021.04.14 |
[spring boot 설정하기-6] querydsl(+JPA) 설정 및 테스트 소스 (0) | 2021.04.09 |
[spring boot 설정하기-5] liquibase 설정 및 연동 (0) | 2021.04.08 |
[spring boot 설정하기-4] Swagger 설정 및 사용 방법 (0) | 2021.04.07 |