Skip to content

Commit

Permalink
Merge pull request #44 from UniBond-jijijin/feature/39-spring-rest-docs
Browse files Browse the repository at this point in the history
[feature/39-spring-rest-docs] Spring REST Docs 사용하기
  • Loading branch information
5jisoo authored Dec 25, 2023
2 parents 664fed1 + 5cc3767 commit 0011463
Show file tree
Hide file tree
Showing 13 changed files with 3,509 additions and 5 deletions.
10 changes: 10 additions & 0 deletions unibond/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ build/
!**/src/main/**/build/
!**/src/test/**/build/

.idea
.tmp
caches
daemon
gradle
jdks
native
wrapper


## key files
application-MYSQL.properties

Expand Down
527 changes: 527 additions & 0 deletions unibond/BOOT-INF/classes/static/docs/experience-community.html

Large diffs are not rendered by default.

524 changes: 524 additions & 0 deletions unibond/BOOT-INF/classes/static/docs/index.html

Large diffs are not rendered by default.

527 changes: 527 additions & 0 deletions unibond/BOOT-INF/classes/static/docs/post.html

Large diffs are not rendered by default.

40 changes: 40 additions & 0 deletions unibond/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
id 'java'
id 'org.springframework.boot' version '3.1.4'
id 'io.spring.dependency-management' version '1.1.3'
id "org.asciidoctor.jvm.convert" version "3.3.2"
}

group = 'com.unibond'
Expand All @@ -15,6 +16,7 @@ configurations {
compileOnly {
extendsFrom annotationProcessor
}
asciidoctorExt
}

repositories {
Expand All @@ -30,9 +32,47 @@ dependencies {
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'

asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor'
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
useJUnitPlatform()
}

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

test {
outputs.dir snippetsDir
}

bootJar {
dependsOn asciidoctor
copy {
from "${asciidoctor.outputDir}"
into 'BOOT-INF/classes/static/docs'
}
}

asciidoctor {
dependsOn test
inputs.dir snippetsDir
}

asciidoctor.doFirst {
delete file('src/main/resources/static/docs')
}

task copyDocument(type: Copy) {
dependsOn asciidoctor
from file("build/docs/asciidoc")
into file("src/main/resources/static/docs")
}

build {
dependsOn copyDocument
}
25 changes: 25 additions & 0 deletions unibond/src/docs/asciidoc/experience-community.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
= Experience Community API
Lucy Oh;
:doctype: book
:icons: font
:source-highlighter: highlishtjs
:toc: left
:toclevels: 4
:sectlinks:

ifndef::snippets[]
:snippets: ./build/generated-snippets
endif::[]

== Get Experience Community Posts

경험 기록 게시판 내용 가져오기

=== Request

include::{snippets}/get-experience-community/http-request.adoc[]

=== Response

include::{snippets}/get-experience-community/http-response.adoc[]
include::{snippets}/get-experience-community/response-fields.adoc[]
38 changes: 38 additions & 0 deletions unibond/src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
= UniBond API Document
Lucy Oh;
:doctype: book
:icons: font
:source-highlighter: highlishtjs
:toc: left
:toclevels: 4
:sectlinks:
:docinfo: shared-head

== Http Status Code

|===
| Status code | Usage

| `200 OK`
| The request completed successfully

| `201 Created`
| A new resource has been created successfully. The resource's URI is available from the response's
`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
|===


== API List

=== Community

* link:experience-community.html[Experience Recording Community API]
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,14 @@
import com.unibond.unibond.post.domain.Post;
import com.unibond.unibond.post.dto.GetCommunityContentDetailResDto;
import com.unibond.unibond.post.dto.GetCommunityResDto;
import com.unibond.unibond.post.dto.PostPreviewDto;
import com.unibond.unibond.post.dto.PostUploadReqDto;
import com.unibond.unibond.post.repository.PostRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.stereotype.Service;

import java.util.stream.Collectors;

import static com.unibond.unibond.common.BaseResponseStatus.DATABASE_ERROR;
import static com.unibond.unibond.common.BaseResponseStatus.INVALID_POST_ID;

Expand Down
636 changes: 636 additions & 0 deletions unibond/src/main/resources/static/docs/experience-community.html

Large diffs are not rendered by default.

524 changes: 524 additions & 0 deletions unibond/src/main/resources/static/docs/index.html

Large diffs are not rendered by default.

527 changes: 527 additions & 0 deletions unibond/src/main/resources/static/docs/post.html

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.unibond.unibond.common;

import org.springframework.restdocs.operation.preprocess.OperationRequestPreprocessor;
import org.springframework.restdocs.operation.preprocess.OperationResponsePreprocessor;

import static org.springframework.restdocs.operation.preprocess.Preprocessors.*;

public interface ApiDocumentUtils {

static OperationRequestPreprocessor getDocumentRequest() {
return preprocessRequest(
prettyPrint());
}

static OperationResponsePreprocessor getDocumentResponse() {
return preprocessResponse(prettyPrint());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package com.unibond.unibond.post.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.restdocs.RestDocumentationContextProvider;
import org.springframework.restdocs.RestDocumentationExtension;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;

import java.util.HashMap;
import java.util.Map;

import static com.unibond.unibond.common.ApiDocumentUtils.getDocumentRequest;
import static com.unibond.unibond.common.ApiDocumentUtils.getDocumentResponse;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.*;
import static org.springframework.restdocs.payload.JsonFieldType.*;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;


@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureRestDocs(uriScheme = "https", uriHost = "docs.api.com")
@ExtendWith({RestDocumentationExtension.class, SpringExtension.class})
class ExperiencePostControllerTest {

@Autowired
MockMvc mockMvc;

@Autowired
WebApplicationContext wac;

ObjectMapper objectMapper = new ObjectMapper();

@BeforeEach
public void setUp(WebApplicationContext webApplicationContext, RestDocumentationContextProvider restDocumentation) {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.addFilter(new CharacterEncodingFilter("UTF-8", true))
.apply(documentationConfiguration(restDocumentation))
.build();
}

@Test
@DisplayName("경험 기록 게시판 조회 Test")
void getExperienceCommunityPosts() throws Exception {
this.mockMvc.perform(
MockMvcRequestBuilders
.get("/api/v1/community/experience")
.contentType(APPLICATION_JSON)
)
.andExpect(status().isOk())
.andDo(document("get-experience-community",
getDocumentRequest(),
getDocumentResponse(),
responseFields(
fieldWithPath("isSuccess").type(BOOLEAN).description("성공 여부"),
fieldWithPath("code").type(NUMBER).description("결과 코드"),
fieldWithPath("message").type(STRING).description("결과 메세지"),
fieldWithPath("result").type(OBJECT).description("결과 데이터"),
fieldWithPath("result.numberOfElements").type(NUMBER).description("반환된 게시글 수"),
fieldWithPath("result.postPreviewList").type(ARRAY).description("게시글 리스트"),
fieldWithPath("result.postPreviewList[].createdDate").type(STRING).description("게시글 작성 일자"),
fieldWithPath("result.postPreviewList[].ownerProfileImg").type(STRING).description("게시글 작성자 프로필 사진"),
fieldWithPath("result.postPreviewList[].ownerNick").type(STRING).description("게시글 작성자 닉네임"),
fieldWithPath("result.postPreviewList[].disease").type(STRING).description("게시글 작성자의 질병"),
fieldWithPath("result.postPreviewList[].contentPreview").type(STRING).description("게시글 미리보기"),
fieldWithPath("result.postPreviewList[].boardType").type(STRING).description("게시글 종류"),
fieldWithPath("result.postPreviewList[].isEnd").type(BOOLEAN).description("미리보기로 제공된 게시글의 내용이 마지막인지 여부"),
fieldWithPath("result.lastPage").type(BOOLEAN).description("현재 마지막 페이지인지 여부"),
fieldWithPath("result.totalPages").type(NUMBER).description("총 페이지 수"),
fieldWithPath("result.totalElements").type(NUMBER).description("총 원소 개수"),
fieldWithPath("result.size").type(NUMBER).description("현재 페이지 사이즈")
)
));
}

@Test
@DisplayName("경험 기록 게시판 게시물 업로드 Test")
void createPost() throws Exception {

Map<String, String> requestMap = new HashMap<>();
requestMap.put("content", "경험 기록 게시판 게시물 업로드 테스트");

String content = objectMapper.writeValueAsString(requestMap);

this.mockMvc.perform(
MockMvcRequestBuilders
.post("/api/v1/community/experience")
.contentType(APPLICATION_JSON)
.content(content)
.header("Authorization", 3)
)
.andExpect(status().isOk())
.andDo(document("post-experience-community",
preprocessRequest(prettyPrint()),
preprocessResponse(prettyPrint())));
}
}

0 comments on commit 0011463

Please sign in to comment.