이번에 Spring REST Docs를 적용하면서 최신 버전의 예시가 없어 헤맸던 부분들을 정리합니다.
Spring REST Docs나 Asciidoctor에 대한 내용은 좋은 문서들이 많이 있으니 생략합니다.
- Spring WebFlux (Functional Endpoints)
- Kotlin (kotest)
- Gradle (Kotlin DSL)
- Spring REST Docs
- Asciidoctor
HelloRouter.kt
@Configuration
class HelloRouter {
@Bean
fun route() = coRouter {
GET("hello") { ServerResponse.ok().bodyValueAndAwait("world") }
}
}
먼저 Spring Boot 프로젝트를 생성하고 간단한 API를 등록합니다.
참고 : https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-fn
build.gradle.kts
testImplementation("org.springframework.restdocs:spring-restdocs-webtestclient")
testImplementation("io.kotest:kotest-runner-junit5:4.6.2")
테스트 파일 생성을 위해 WebTestClient와 kotest dependency를 추가합니다.
kotest가 아닌 다른 Test framework를 사용해도 됩니다.
HelloRouterTests.kt
class HelloRouterTests : WordSpec({
val restDocumentation = ManualRestDocumentation() // 1
val webTestClient = WebTestClient.bindToRouterFunction(HelloRouter().route())
.configureClient()
.filter(documentationConfiguration(restDocumentation))
.build()
beforeEach {
restDocumentation.beforeTest(javaClass, "HelloRouterTests") // 2
}
afterEach {
restDocumentation.afterTest() // 2
}
"hello" should {
"return world" {
webTestClient.get().uri("/hello").exchange().expectStatus().isOk.expectBody()
.consumeWith(
document("hello", // 3
preprocessRequest(prettyPrint()),
preprocessResponse(prettyPrint())
)
)
}
}
})
테스트 파일을 생성합니다.
1. JUnit을 사용하는 경우 ManualRestDocumentation이 아닌 JUnitRestDocumentation을 사용해야 합니다.
2. ManualRestDocumentation의 경우 각 테스트의 시작, 종료 시 beforeTest와 afterTest를 호출해야 합니다.
3. 테스트가 성공하면 document에 입력한 identifier명으로 build/generated-snippets아래에 asciidoctor 파일이 생성됩니다.
참고 : https://docs.spring.io/spring-restdocs/docs/current/reference/html5/
index.adoc
= Hello API Document
:doctype: book
:source-highlighter: highlightjs
:toc: left
:toclevels: 2
:sectlinks:
[[Hello]]
== Hello API
include::hello.adoc[] // 1
hello.adoc
operation::hello[snippets='curl-request,http-request,http-response'] // 2
asciidoctor 파일을 생성합니다.
기본 위치는 /src/docs/asciidoc 입니다.
1. include는 외부의 파일을 포함하는 기능으로 경로와 파일명을 적어줍니다.
상대 경로이기 때문에 경로 설정이 필요합니다.
참고 : https://docs.asciidoctor.org/asciidoc/latest/directives/include/
2. operation은 snippets을 쉽게 추가할 수 있는 기능으로 Spring REST Docs에 정의되어 있습니다.
이 기능을 사용하기 위해서는 약간의 추가 설정이 필요합니다.
build.gradle.kts
plugins {
id("org.asciidoctor.jvm.convert") version "3.3.2" // 1
}
val asciidoctorExtensions by configurations.creating // 2
dependencies {
asciidoctorExtensions("org.springframework.restdocs:spring-restdocs-asciidoctor:2.0.5.RELEASE") // 2
}
tasks.asciidoctor {
dependsOn(tasks.test) // 3
configurations(asciidoctorExtensions.name) // 2
baseDirFollowsSourceDir() // 4
doLast {
copy {
from(outputDir)
into("src/main/resources/static/docs")
}
} // 5
}
tasks.build {
dependsOn(tasks.asciidoctor)
} // 6
생성한 asciidoctor 파일에 snippets을 추가한 파일 생성을 위해 gradle 설정을 추가합니다.
1. asciidoctor convert 를 추가합니다. spring initializr에서 Spring REST Docs를 추가하면 org.asciidoctor.convert가 추가되는데 옛날 버전이라고 하니 org.asciidoctor.jvm.convert로 변경합니다.
2. asciidoctor에서 operation기능을 사용하기 위한 설정입니다. groovy 버전 스크립트는 아래 공식 가이드를 참고하시면 됩니다.
3. test가 완료되어야 snippets 파일이 생성되므로 test 이후에 실행되도록 설정합니다.
4. 기본 경로를 /src/docs/asciidoc 으로 설정해 줍니다. include 파일의 경로를 맞춰주기 위한 설정입니다. 4가지 설정이 있으니 정상 동작하지 않으면 공식 가이드를 참고하여 변경하시면 됩니다.
5. 최종 생성된 파일을 resources 디렉토리로 복사해 주는 기능입니다. /build/docs/asciidoc 경로에 생성된 파일이 /resources/static/docs 경로로 복사됩니다.
6. build할 때 자동으로 문서를 생성하려면 dependsOn 설정을 추가합니다.
참고 : https://asciidoctor.github.io/asciidoctor-gradle-plugin/development-3.x/user-guide/
ApplicationConfig.kt
@Configuration
class ApplicationConfig : WebFluxConfigurer {
override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
registry.addResourceHandler("/static/docs/**")
.addResourceLocations("classpath:/static/docs/")
.resourceChain(false)
}
}
resources 파일을 Spring Boot에 등록합니다.
이 설정 이후에 asciidoctor 파일을 서버에서 조회할 수 있습니다.
http://localhost:8080/static/docs/index.html
'개발 > Spring' 카테고리의 다른 글
Spring Webflux Functional Endpoints 에서 request, response logging 하기 (0) | 2021.11.10 |
---|
댓글