Spring REST API - Spring REST Docs
Spring REST Docs 는 소스에 관한 설명을 제공할 수 있는 정형화된 documents 를 만드는 기능을 제공한다.
Docs 를 만들 때 swagger 를 사용할 수도 있지만, Spring REST Docs 로 만들어보자.
Spring Docs 에서 문서 조각을 snippets
라 한다. 문서 조각이 모인 Docs를 Asciidoctor
조립하여 HTML 문서를 만든다.
테스트
- MockMvc
- WebTestClinet
- REST Aussured 등등
REST Docs 를 사용해보자.
pom.xml 에 REST Docs 의존성을 추가한다.
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<scope>test</scope>
</dependency>
이제 테스트 클래스에 @AutoConfigureRestDocs
어노테이션을 붙이고, .andDo(document("제목"))
docs 파일을 만들어보자
스프링부트에서 REST Doc 자동설정은 @AutoConfigureRESTDocs
를 사용하면 된다.
@SpringBootTest
@AutoConfigureRestDocs
public class EventControllerTest {
...
@Test
public void createEvent() throws Exception {
...
mockMvc.perform(post("/api/events")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaTypes.HAL_JSON)
.content(objectMapper.writeValueAsString(event))
)
.andDo(print())
.andExpect(status().isCreated())
.andDo(document("create-event")) // Document 생성
;
}
}
실행시키면 target/generated-snippets/
에 create-event 폴더가 생기고, docs 파일들이 만들어진다.
andDo(document("문서이름", snippets))
의 형태로 사용하면 된다.
RestDocMockMvc 커스터마이징
커스마이징할 설정 파일을 test 폴더 하위에 놓으면 된다.
test/common/RestDocsConfiguration.java
...
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
@TestConfiguration
public class RestDocsConfiguration {
@Bean
public RestDocsMockMvcConfigurationCustomizer restDocsMockMvcConfigurationCustomizer() {
return configurer -> configurer.operationPreprocessors()
.withRequestDefaults(prettyPrint())
.withResponseDefaults(prettyPrint());
}
}
@TestConfiguration
어노테이션을 붙이면 테스트 환경 설정을 수정할 수 있다.
여러 프로세서가 있는데 그 중 pretty printer
를 사용하였다. 조금 더 예쁘게 프린팅할 수 있다.
이로써 요청 본문과 응답 본문을 '예쁘게' 문서화 시킬 수 있다.
@SpringBootTest
@AutoConfigureRestDocs
@Import(RestDocsConfiguration.class)
public class EventControllerTest {
...
}
다시 실행하면 기존에 있던 것을 날리고, 덮어씌운다.
문서화
링크 문서화
.andDo(document("create-event",
links(
linkWithRel("self").description("link to self"),
linkWithRel("query-events").description("link to query events"),
linkWithRel("update-event").description("link to update event")
)
))
links() 함수를 추가하면, 링크정보를 담은 links.adoc
파일이 생성된다.
요청 헤더, 요청 필드 문서화
requestHeaders(
headerWithName(HttpHeaders.ACCEPT).description("accept header"),
headerWithName(HttpHeaders.CONTENT_TYPE).description("content type header")
),
requestFields(
fieldWithPath("name").description("name of event"),
...
fieldWithPath("limitOfEnrollment").description("limitOfEnrollment of event")
),
request-headers.adoc
, request-fields.adoc
문서가 생성된다.
응답 헤더, 응답 필드 문서화
responseHeaders(
headerWithName(HttpHeaders.LOCATION).description("location header"),
headerWithName(HttpHeaders.CONTENT_TYPE).description("content type header")
),
responseFields(
fieldWithPath("id").description("id of event"),
...
fieldWithPath("eventStatus").description("eventStatus of event"),
fieldWithPath("_links.self.href").description("link to self"),
fieldWithPath("_links.query-events.href").description("link to query events"),
fieldWithPath("_links.update-event.href").description("link to update event")
)
응답의 경우 HATEOAS 를 위해 만든 _links 정보도 모두 입력해주어야 한다. 이렇게 모두 작성해주는 것이 바람직하다. 나중에 API 가 변경되었을 경우 보고 찾아서 판단할 수 있는 토대가 되기 때문이다.
모두 서술하는 것을 원하지 않는다면 일부만 서술하기 위해 relaxedResponseFields
를 사용한다.
// 예시) 링크정보는 넣지 않음.
relaxedResponseFields(
fieldWithPath("id").description("id of event"),
...
fieldWithPath("eventStatus").description("eventStatus of event")
)
이렇게 해도 테스트 에러없이 다큐먼트를 만들 수 있다.
REST Docs 문서 빌드하기
/src/main/asciidoc/index.adoc
폴더를 만들고, 문서 포맷과 내용을 복사한다.
pom.xml 에 플러그인을 추가한다.
<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>
<backend>html</backend>
<doctype>book</doctype>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-asciidoctor</artifactId>
<version>${spring-restdocs.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.outputDirectory}/static/docs
</outputDirectory>
<resources>
<resource>
<directory>
${project.build.directory}/generated-docs
</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
- line 10:
process-asciidoc
은 asciidoc 아래 있는 모든 adoc 문서를 html로 변환해준다. - line 34:
copy-resources
는 소스 데이터 (generated-docs) 를 출력 디렉토리에/static/docs
폴더 아래 만들어준다. 이 경로는 빌드 후에static
폴더 아래 생기므로http://localhost:8080/docs/{파일이름.html}
로 요청하면 화면에 html 화면이 나타날 수 있다.
이제 mvn package
를 실행하면, test 가 실행될 때 process-asciidoc
과 copy-resources
가 실행된다.
그렇다면 이제 애플리케이션을 실행시키면, http://localhost:8080/docs/index.htm 에 접속이 가능할 것이다.
이 중 이벤트 생성의 url은 http://localhost:8080/docs/index.html#resources-events-create
와 같다. 따라서 REST API의 self-descriptive message 조건을 위해 create-event
의 셀프 설명 문서는 위 url을 참고하도록 하자.
컨트롤러 수정.
@PostMapping
public ResponseEntity createEvent(@RequestBody @Valid EventDto eventDto, Errors errors) {
...
eventResource.add(new Link("/docs/index.html#resources-events-create").withRel("profile"));
return ResponseEntity.created(createdUri).body(eventResource);
}
테스트 수정.
links(
...
linkWithRel("profile").description("link to profile")
),
...,
responseFields(
...
fieldWithPath("_links.profile.href").description("link to profile")
)
'Java, Kotlin, Spring > Spring REST API' 카테고리의 다른 글
Spring REST API - 조회 테스트 (0) | 2021.01.28 |
---|---|
Runtime, Test DB 설정 (0) | 2021.01.27 |
Spring REST API - HATEOAS (0) | 2021.01.24 |
Spring REST API - 테스트코드 파라미터사용 (0) | 2021.01.23 |
Spring REST API - BadRequest (0) | 2021.01.23 |
댓글