ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • spring restdoc 을 만들어 보자
    카테고리 없음 2023. 4. 19. 09:55

    spring restdoc 을 만들어 보자

    restdoc을 쓸수도 있을 거 같아서 정리 한다. spring-boot 기준으로 작성 하였다. 기본적인 spring-boot를 안다고 가정하고 작성한다.

    ... <dependency> <groupId>org.springframework.restdocs</groupId> <artifactId>spring-restdocs-mockmvc</artifactId> <version>1.0.1.RELEASE</version> </dependency> .... <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <includes> <include>**/*Documentation.java</include> </includes> </configuration> </plugin> <plugin> <groupId>org.asciidoctor</groupId> <artifactId>asciidoctor-maven-plugin</artifactId> <version>1.5.2.1</version> <executions> <execution> <id>generate-docs</id> <phase>prepare-package</phase> <goals> <goal>process-asciidoc</goal> </goals> <configuration> <backend>html</backend> <doctype>book</doctype> <attributes> <snippets>${project.build.directory}/generated-snippets</snippets> </attributes> </configuration> </execution> </executions> </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> ...
    restdocs-mockmvc 디펜더시랑 plugin 을 추가하자. 필자의 파일 경로로 하지 않아도 된다. 필자는 generated-snippets 에 snippets 설정 했다. 여기에 실제 adoc 파일들이 추가된다. 그리고 테스트 케이스를 만들어야 된다. 테스트 케이스는 기존에 필자가 포스팅 한거랑 비슷한대 약간 추가 되는 부분이 있다. 살펴보자
    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = SpringTestApplication.class)
    @WebAppConfiguration
    @FixMethodOrder(MethodSorters.JVM)
    public class AccountControllerTest {
    
        @Autowired
        private WebApplicationContext webApplicationContext;
    
        MockMvc mockMvc;
    
    
        @Autowired
        private ObjectMapper objectMapper;
    
    
        @Rule
        public RestDocumentation restDocumentation =
                new RestDocumentation("target/generated-snippets");
    
        @Before
        public void before() {
            this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext)
                    .apply(documentationConfiguration(this.restDocumentation))
    //                .alwaysDo(document("{method-name}/{step}/"))
                    .alwaysDo(document("{class-name}/{method-name}/"))
                    .build();
        }
    
        @Test
        public void getAccounts() throws Exception {
            this.mockMvc.perform(get("/accounts").accept(MediaType.APPLICATION_JSON))
                    .andExpect(status().isOk())
                    .andExpect(jsonPath("$.[0].name", is("wonwoo")));
        }
    
        @Test
        public void getAccount() throws Exception {
            this.mockMvc.perform(get("/account/{id}", 1).accept(MediaType.APPLICATION_JSON))
                    .andDo(print())
                    .andExpect(status().isOk())
                    .andExpect(jsonPath("$.name", is("wonwoo")));
        }
    
        @Test
        public void createAccount() throws Exception {
            Account account = new Account();
            account.setName("wonwoo123");
            this.mockMvc.perform(post("/account").contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(account)))
                    .andDo(print())
                    .andExpect(status().isOk())
                    .andExpect(jsonPath("$.name",is("wonwoo123")));
        }
    }
    
    나머진 일반 테스트 케이스처럼 작성하면 되고 before 부분만 변경 되었다. before의 alwaysDo 메소드에 있는 class-name과 method-name은 위에서 말했던 generated-snippets/* 폴더 아래에 classname/methodname/ 형식으로 추가된다. 작성 후에 테스트를 실행 하여 보자. 만약 성공 되었다면 target/generated-snippets/ 아래 폴더에 파일들이 생성 되어있는걸 볼 수 있다. 그리고 나서 src/main/asciidoc/index.adoc 를 추가하자. (필자 기준)
    = RESTful Notes API Guide
    Andy Wilkinson;
    :doctype: book
    :icons: font
    :source-highlighter: highlightjs
    :toc: left
    :toclevels: 4
    :sectlinks:
    
    [[overview]]
    = Overview
    
    [[overview-http-verbs]]
    == HTTP verbs
    
    RESTful notes tries to adhere as closely as possible to standard HTTP and REST conventions in its
    use of HTTP verbs.
    
    |===
    | Verb | Usage
    
    | `GET`
    | Used to retrieve a resource
    
    | `POST`
    | Used to create a new resource
    
    | `PATCH`
    | Used to update an existing resource, including partial updates
    
    | `DELETE`
    | Used to delete an existing resource
    |===
    
    [[overview-http-status-codes]]
    == HTTP status codes
    
    RESTful notes tries to adhere as closely as possible to standard HTTP and REST conventions in its
    use of HTTP status codes.
    
    |===
    | Status code | Usage
    
    | `200 OK`
    | The request completed successfully
    
    | `201 Created`
    | A new resource has been created successfully. The resources URI is available from the responses
    `Location` header
    
    | `204 No Content`
    | An update to an existing resource has been applied successfully
    
    | `400 Bad Request`
    | The request was malformed. The response body will include an error providing further information
    
    | `404 Not Found`
    | The requested resource did not exist
    |===
    
    
    == 사용자 리스트 조회 [get]
    
    사용자를조회
    
    
    include::{snippets}/account-controller-test/get-accounts/curl-request.adoc[]
    
    === 요청 구조
    
    ==== 요청 파라미터들
    
    include::{snippets}/account-controller-test/get-accounts/http-request.adoc[]
    
    === 응답 구조
    
    ==== 응답 파라미터들
    
    include::{snippets}/account-controller-test/get-accounts/http-response.adoc[]
    
    
    
    == 사용자 조회 [get]
    
    사용자를조회
    
    
    include::{snippets}/account-controller-test/get-account/curl-request.adoc[]
    
    === 요청 구조
    
    ==== 요청 파라미터들
    
    include::{snippets}/account-controller-test/get-account/http-request.adoc[]
    
    === 응답 구조
    
    ==== 응답 파라미터들
    
    include::{snippets}/account-controller-test/get-account/http-response.adoc[]
    
    
    == 사용자 입력 [post]
    
    사용자를조회
    
    
    include::{snippets}/account-controller-test/create-account/curl-request.adoc[]
    
    === 요청 구조
    
    ==== 요청 파라미터들
    
    include::{snippets}/account-controller-test/create-account/http-request.adoc[]
    
    === 응답 구조
    
    ==== 응답 파라미터들
    
    include::{snippets}/account-controller-test/create-account/http-response.adoc[]
    
    
    
    윗 부분은 spring에서 퍼온거라.. asciidoc이라는 문법이다. asciidoc-syntax-quick-reference 문법은 여기서 참고. == 사용자 리스트 조회 [get] 이 부분 부터가 필자가 만들었다. 이쁘진 않지만.. 나머지는 그냥 다 문법이고 추가 해야 되는 부분이 있는데 include하는 이 부분이다. 위에서 말했던 파일들을 include 하는 부분이다. 저기에 각각의 페이지가 include 된다. 실제 파일들이 어떻게 생겼는지 보자. curl이 작성 되어있다. 파일명은 curl-request.adoc로 떨궈진다.
    [source,bash]
    ----
    $ curl http://localhost:8080/accounts -i -H Accept: application/json
    ----
    
    
    다음으로 reqeust 정보이다. 실제 rest api 의 method, resource, message 정보들이 적혀있다. (물론 지금은 메시지가 없어서)
    [source,http]
    ----
    GET /accounts HTTP/1.1
    Accept: application/json
    Host: localhost
    
    ----
    
    마지막으로 response 정보이다. 실제 서버에서 내려 받은 정보를 보여준다.
    [source,http]
    ----
    HTTP/1.1 200 OK
    Content-Type: application/json;charset=UTF-8
    Content-Length: 81
    
    [ {
      "id" : 1,
      "name" : "wonwoo"
    }, {
      "id" : 2,
      "name" : "kevin"
    } ]
    ----
    
    메이븐 기준으로 되어있으니 메이븐을 실행해보자.
    mvn install
    
    그러면 target/generated-docs 아래 index.html 파일이 생성 되어 있을 것이다. 한번 열어 보자! 그럼 깔끔한 api 문서가 만들어져있다. spring-doc 잘 실행되었다면 위와 같은 화면을 볼 수 있을 것이다.

    댓글

Designed by Tistory.