AgentSkillsCN

restdocs

Spring REST Docs测试编写规则、Field DSL、常见响应模式,以及AsciiDoc生成规范

SKILL.md
--- frontmatter
name: restdocs
description: Spring REST Docs test writing rules, Field DSL, common response patterns, and AsciiDoc generation
triggers:
  - restdocs
  - api docs
  - documentation
  - asciidoc
argument-hint: ""

REST Docs rules

Overview

This document defines rules for writing Spring REST Docs tests using the project's RestDocsSupport base class, Field DSL, and common response patterns.

Key Principle: Extend RestDocsSupport, mock the Facade, and use DocsFieldType and Field DSL for all documentation tests.

Note: Full documentation is available in the .docs/restdocs/ directory.

DocumentContents
.docs/restdocs/01-overview.adocDirectory structure, core components, DocsFieldType, Field DSL
.docs/restdocs/02-writing-tests.adocStep-by-step DocsTest writing guide, common response patterns
.docs/restdocs/03-examples.adocHolidayControllerDocsTest analysis, AsciiDoc document authoring
.docs/restdocs/04-reference.adocBest practices, troubleshooting, checklist, build commands

Core rules

1. Extend RestDocsSupport

All DocsTests must extend RestDocsSupport.

kotlin
class MyControllerDocsTest : RestDocsSupport() {

    private val myFacade: MyFacade = mock()

    override fun initController(): Any = MyController(myFacade)
}

2. Mock the Facade

Controllers depend on Facades. Mock the Facade in your DocsTests.

kotlin
// Good: Mock the Facade
private val holidayFacade: HolidayFacade = mock()
override fun initController(): Any = HolidayController(holidayFacade)

// Bad: Mock the Service directly
private val holidayService: HolidayService = mock()

3. Use DocsFieldType

TypeJSON TypeAuto format
STRINGString-
NUMBERNumber-
BOOLEANBoolean-
ARRAYArray-
OBJECTObject-
DATEStringyyyy-MM-dd
DATETIMEStringyyyy-MM-dd'T'HH:mm:ss
ENUM(Class::class)StringLists enum values

4. Field DSL (infix functions)

kotlin
"fieldName" type TYPE means "description"
"fieldName" type TYPE means "description" isOptional true
"fieldName" type TYPE means "description" example "sample value"
"fieldName" type TYPE means "description" withDefaultValue "default"

5. Response strategy

StrategyMethodUse case
Full fieldsresponseCommonFields() + fields()Few and simple fields
SubsectionresponseCommonFieldsSubsection() + dataResponseFields()Many or complex fields (recommended)
kotlin
// Subsection strategy (recommended)
responseFields(*responseCommonFieldsSubsection()),
dataResponseFields(
    "id" type NUMBER means "ID",
    "name" type STRING means "이름",
)
Response typeSubsection methodFull fields method
Single objectresponseCommonFieldsSubsection()responseCommonFields()
ArrayresponseArrayCommonFieldsSubsection()responseArrayCommonFields()
String (DELETE, etc.)-responseStringCommonFields()

6. Pagination response

kotlin
mockMvc.perform(
    get("/api/resources/{id}", 1)
        .param("page", "0")
        .param("size", "20")
)
    .andExpect(status().isOk)
    .andDo(
        restDocs.document(
            queryParameters(
                *pageRequestFormat().toTypedArray(),
            ),
            responseFields(
                *responseArrayCommonFieldsSubsection(),
                subsectionWithPath("meta.pageInfo").type(JsonFieldType.OBJECT)
                    .optional().description("페이지 정보"),
            ),
            responseFields(
                beneathPath("meta.pageInfo").withSubsectionId("data.page"),
                *pageCommonFormat().toTypedArray(),
            ),
            dataResponseFields(
                "id" type NUMBER means "ID",
            ),
        )
    )

7. Test method naming

Test method names become snippet directory names. Use clear English names.

kotlin
// Good: Meaningful snippet directory names
fun `get holidays by year`(): Unit { }       // -> get-holidays-by-year/
fun `create holiday`(): Unit { }             // -> create-holiday/

// Bad: Unclear directory names
fun `should return holidays`(): Unit { }     // -> should-return-holidays/

8. Write field descriptions in Korean

IMPORTANT: Write field descriptions in REST Docs in Korean. This is a project convention.

kotlin
// Good
"data.name" type STRING means "공휴일 이름"

// Bad
"data.name" type STRING means "holiday name"

Quick reference

kotlin
// Single object response
responseFields(*responseCommonFieldsSubsection()),
dataResponseFields("id" type NUMBER means "ID")

// Array response
responseFields(*responseArrayCommonFieldsSubsection()),
dataResponseFields("id" type NUMBER means "ID")

// String response (DELETE, etc.)
responseFields(*responseStringCommonFields())

// Request fields
requestFields(*fields("name" type STRING means "이름"))

// Path parameters
pathParameters(parameterWithName("id").description("ID"))

Build

bash
# Generate HTML docs (test -> snippets -> HTML)
./gradlew clean :modules:docs:docs

# Run a specific test only
./gradlew test --tests "com.myrealtrip.commonapiapp.docs.HolidayControllerDocsTest"

Summary checklist

  • Extend RestDocsSupport
  • Mock the Facade (not Service)
  • Use DocsFieldType (DATE, DATETIME, ENUM, etc.)
  • Use Field DSL: type, means infix functions
  • Write field descriptions in Korean
  • Use pageRequestFormat() and pageCommonFormat() for pagination responses
  • Use clear English test method names
  • Mark optional fields with isOptional true