API 문서를 작성하는 과정에서 사용한 Spring rest docs 도입 과정을 포스팅하려고 한다.
Spring API 문서 자동화에는 대표적으로 Swagger
와 Spring Rest Docs
가 있지만, 테스트 코드 작성에 강제성을 부여하기 위해 Spring Rest Docs
를 선택하게 되었다.
// Asciidoctor 플러그인 적용 👉 AsciiDoc 파일 컨버팅
plugins {
id 'org.asciidoctor.convert' version "1.5.9.2"
}
// build/generated-snippets 경로에 스니펫 생성
ext {
set('snippetsDir', file("build/generated-snippets"))
}
// 의존성 추가
dependencies {
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
asciidoctor 'org.springframework.restdocs:spring-restdocs-asciidoctor'
}
// gradle build 시 test 👉 asciidoctor 순으로 실행
asciidoctor {
inputs.dir snippetsDir
dependsOn test
}
// gradle build시 ./build/asciidoc/html/ 에 html 파일 생성
bootJar { // SpringBoot 1.5 이하일 경우 jar
dependsOn asciidoctor
from("${asciidoctor.outputDir}/html5") {
into 'static/docs'
}
}
Spring rest docs
사용하기 위해서는 테스트 코드를 필수로 작성해야 한다.
@WebMvcTest
는 web 레이어 관련 빈(Controller 관련 빈)들만 등록해서 사용하므로 @SpringBootTest
에 비해 비교적 가볍고 빠르다. 따라서 이번 프로젝트에서는 @WebMvcTest
을 이용한 테스트 코드를 작성한다.
@ExtendWith(RestDocumentationExtension.class) // (1)
@WebMvcTest(UserApiController.class) // (2)
@MockBean(JpaMetamodelMappingContext.class) // (3)
class UserApiControllerTest {
...
}
JUnit 5
를 사용할 때 문서 스니펫 생성을 위해 RestDocumentationExtension
을 테스트 클래스에 적용해야 한다.Controller
관련 빈들만 등록되는 @WebMvcTest
를 사용한다.JPA Auditing
기능 사용을 위해 application에 @EnableJPaAuditing
을 적용했다면, 해당 어노테이션을 추가해야 한다. @WebMvcTest
는 JPA 생성과 관련된 기능을 제공하지 않는다.
@ExtendWith(RestDocumentationExtension.class)
@WebMvcTest(UserApiController.class)
@MockBean(JpaMetamodelMappingContext.class)
class UserApiControllerTest {
private MockMvc mockMvc;
// MockMvc 설정
@BeforeEach
public void setup(WebApplicationContext webApplicationContext, RestDocumentationContextProvider restDocumentation) {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.apply(documentationConfiguration(restDocumentation))
.apply(sharedHttpSession())
.build();
}
}
MockMvc 설정을 직접 추가하는 방법이다.
@Test
@DisplayName("이메일 중복 체크 -> 이메일 중복")
void checkEmailDuplicate_failure() throws Exception {
String email = "HongJungWan@test.com";
given(userService.checkEmailDuplicate(email)).willReturn(true);
mockMvc.perform(get("/users/user-emails/{email}/exists", email))
.andExpect(status().isOk())
.andExpect(content().string("true"));
}
@Test
@DisplayName("이메일 중복 체크 -> 이메일 중복")
void checkEmailDuplicate_failure() throws Exception {
String email = "HongJungWan@test.com";
given(userService.checkEmailDuplicate(email)).willReturn(true);
mockMvc.perform(get("/users/user-emails/{email}/exists", email))
.andExpect(status().isOk())
.andExpect(content().string("true"))
.andDo(document("users/duplicateEmail/failure",
pathParameters(
parameterWithName("email").description("이메일"))));
}
requestFields
, pathParameters
, responseFields
등 다양한 메서드들을 제공한다.
테스트 코드에 Spring Rest Docs 관련 코드까지 추가하고 테스트를 실행 후 테스트가 정상적으로 통과되었다면 아래와 같이 기본 경로에 snippets이 생성된다.
기본 경로 : ./build/generated-snippets
// snippets 생성 경로
.andDo(document("users/duplicateEmail/failure"))
snippets 작성은 아래 경로에 .adoc 확장자로 asciidoc 파일을 만들어 작성해야 한다.
Build tool | Source files | Generated files |
---|---|---|
Maven | src/main/asciidoc/*.adoc | target/generated-docs/*.html |
Gradle | src/docs/asciidoc/*.adoc | build/asciidoc/html5/*.html |
asciidoc에 API 문서를 작성 후 gradle build를 진행하면 ./build 폴더에 asciidoc 이라는 폴더가 생성되면서 그 안에 html 파일이 생성된다.
✅ intelliJ를 사용한다면 AsciiDoc 플러그인을 다운로드해 .adoc 파일에서 편하게 작업이 가능하다.
Tasks - build - build
를 실행하면 gradle에서 설정한 순서에 따라 build가 진행된다.
build가 완료되면 아래 경로에 html 파일이 생성된 걸 확인할 수 있다.
완성된 API Guide