Project/DARLING

5. Spring REST Docs 사용

서비스 구현에 앞서 REST API 문서를 자동화 해주는 Spring REST Docs 를 사용해본다.

Docs를 사용한 이유는 Test에서 성공해야만 문서를 만들 수 있기 때문에 사용하게되었습니다.

강제로 TEST CODE를 작성하여 API에 대한 신뢰성을 높일 수 있기 때문입니다.

 

Gradle 7을 사용하고 있었는데 문서생성이 안되서 검색해봤다.

우회방법이 있지만 복잡하기 때문에 다운그레이드를 선택했다.

 

그리고 Gradle과 Maven 에서 다르게 설정되는 부분이 있기 때문에 맨아래 링크를 통해 확인해보는 것도 좋다!

 

환경설정
Springboot 2.6.1
Gradle 6.9.1
JUnit5
Asciidoctor 1.5.9.2

build.gradle 에 추가한 설정

plugins {
   
    id "org.asciidoctor.convert" version "1.5.9.2"
}

dependencies {
    asciidoctor 'org.springframework.restdocs:spring-restdocs-asciidoctor'
    testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
}

ext {
    snippetsDir = file('build/generated-snippets')
}

test {
    useJUnitPlatform()
    outputs.dir snippetsDir
}

asciidoctor {
    inputs.dir snippetsDir
    dependsOn test
}

bootJar {
    dependsOn asciidoctor
    from ("${asciidoctor.outputDir}/html5") {
        into 'static/docs'
    }
}

task copyDocument(type: Copy) {
    dependsOn asciidoctor

    from file("build/asciidoc/html5/")
    into file("src/main/resources/static/docs")
}

build {
    dependsOn copyDocument
}

문서는 Build할 때 build/asciidoc/html5/ 에 저장되는데 src/main/resources/static/docs 에도 복사가 되어 배포시

따로 확인할 수 있도록 설정했습니다.

 

TEST CODE 설정

@ExtendWith(RestDocumentationExtension.class)
@SpringBootTest
class UserRegisterControllerTest {

  private MockMvc mockMvc;

  @BeforeEach
  public void setUp(
      WebApplicationContext webApplicationContext,
      RestDocumentationContextProvider restDocumentation) {
    this.mockMvc =
        MockMvcBuilders.webAppContextSetup(webApplicationContext)
            .apply(documentationConfiguration(restDocumentation))
            .build();
  }

}

일반적인 MockMvc 세팅 에 추가로 apply(documentationConfiguration(restDocumentation)) 을 추가 해주어 문서화를 할 수 있도록 설정했습니다.

 

유저 생성 테스트

@Test
  void create() throws Exception {
    final UserRegisterResponse userRegisterResponse = UserRegisterResponse.builder().id(1L).build();
    when(userRegisterService.addUser(any())).thenReturn(userRegisterResponse);

    this.mockMvc
        .perform(
            post("/user")
                .content("{\"socialToken\":\"abc\"}")
                .contentType(MediaType.APPLICATION_JSON))
        .andExpect(status().isCreated())
        .andDo(document("user-create",requestFields(
                fieldWithPath("socialToken").description("소셜토큰")
        )));
  }

post 메서드 이기 때문에 content에 필요한 파라미터를 json 방식으로 입력해줍니다.

 

1. user-create 는 아래와 같이 build파일 내에 생기는 이름을 설정해줍니다.

2. fieldWithPath().description() 은 아래와 같이 출력해줄 수 있습니다.

 

마지막으로 src/docs/asclidoc/api-docs.adoc 를 만들어서 아래와 같이 작성합니다.

* api-docs 는 http://localhost:8080/docs/api-docs.html 와 같이

html 파일의 이름을 정해주기 때문에 관련된 이름으로 지어줍니다.

 

공식문서 참고 ( 번역본도 있는듯... )

https://docs.asciidoctor.org/asciidoctor/latest/

 

Asciidoctor - Asciidoctor Documentation

A documentation page for Asciidoctor.

docs.asciidoctor.org

= Spring REST Docs
:toc: left
:toclevels: 2
:sectlinks:

[[resources-post]]
== User

[[resources-post-create]]
=== User 생성

==== Request Fields

include::{snippets}/user-create/request-fields.adoc[]

==== HTTP request

include::{snippets}/user-create/http-request.adoc[]

==== HTTP response

include::{snippets}/user-create/http-response.adoc[]

include 에 해당하는 adoc는 build/generated-snippets 에서 확인할 수 있습니다!

 

 

서버 실행후 

http://localhost:8080/docs/api-docs.html 로 접속하면 문서가 만들어진것을 확인할 수 있습니다!

 

+ 2022.02.09 List 조회

List로 된 Response일 경우 fieldWithPath를 아래와 같이 []. 를 붙여준다 

이유는 -> https://docs.spring.io/spring-restdocs/docs/2.0.4.RELEASE/reference/html5/#documenting-your-api-request-response-payloads-fields-reusing-field-descriptors

@Test
  void findAllWish() throws Exception {
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy년 MM월 dd일 E요일", Locale.KOREAN);

    final List<WishListFindAllResponse> wishListFindAllResponse =
        Lists.newArrayList(
            WishListFindAllResponse.builder()
                .wishListId(1L)
                .complete_date(null)
                .register_date(
                    simpleDateFormat.format(java.sql.Timestamp.valueOf(LocalDateTime.now())))
                .content("바다 가기")
                .wishUserNickname("애정")
                .status(WishStatus.INCOMPLETE)
                .build());

    when(wishFindService.findAllWish(any())).thenReturn(wishListFindAllResponse);

    this.mockMvc
        .perform(get("/wishlists/{coupleToken}", "AAAAA").accept(MediaType.APPLICATION_JSON))
        .andExpect(status().isOk())
        .andDo(
            document(
                "wish-find-all",
                pathParameters(parameterWithName("coupleToken").description("커플 토큰")),
                responseFields(
                    fieldWithPath("[].wishListId").description("위시 고유 ID"),
                    fieldWithPath("[].content").description("위시 내용"),
                    fieldWithPath("[].register_date").description("위시 생성 날짜"),
                    fieldWithPath("[].complete_date").description("위시 완료 날짜"),
                    fieldWithPath("[].wishUserNickname").description("위시 생성한 유저의 닉네임"),
                    fieldWithPath("[].status").description("위시 상태"))));
  }

 

 

 

 

참고 

https://tecoble.techcourse.co.kr/post/2020-08-18-spring-rest-docs/

 

API 문서 자동화 - Spring REST Docs 팔아보겠습니다

프로덕션 코드와 분리하여 문서 자동화를 하고 싶다고요? 신뢰도 높은 API 문서를 만들고 싶다고요? 테스트가 성공해야 문서를 만들 수 있다!! Spring REST Docs가 있습니다. API 문서를 자동화 도구로

tecoble.techcourse.co.kr

https://blog.hodory.dev/2019/12/04/spring-rest-docs-with-gradle-not-working-html5/

 

[Java]Spring REST Docs HTML이 생성되지 않을때

백기선님의 스프링부트 강좌를 수강하는중에 Spring REST Docs를 이용하여 HTML을 생성하려하는데,아무리 빌드를 해도 ascii\html\index.html이 생성되지 않았습니다. 12345678910111213141516171819202122232425262728293

blog.hodory.dev

 

'Project > DARLING' 카테고리의 다른 글

7. CI/CD 계획  (0) 2022.02.09
6. 무엇이 문제일까 ...  (0) 2022.01.25
4. 연관관계 - OneToMany  (0) 2022.01.23
3. 연관관계 - ManyToOne  (0) 2022.01.23
2. Entity  (0) 2021.12.03