카테고리 없음

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 잘 실행되었다면 위와 같은 화면을 볼 수 있을 것이다.