Skip to content

Commit

Permalink
[BE] Spring Rest Docs 기능 추가 (#23)
Browse files Browse the repository at this point in the history
* Feat: Spring Rest Docs 의존성 추가 - #14

- Gradle 버전에 맞게 Spring Rest Docs 의존성 추가

* Feat: 개발 환경, 테스트 환경 분리 - #14

- 테스트 환경을 분리하여 H2 DB 연결

* Feat: Spring Rest Docs 기능 추가 (테스트한 더미 데이터 추가되지 않음) - #14

- 테스트를 통한 API 명세를 확인하기 위해 Spring Rest Docs 추가
- 테스트한 더미 데이터는 추가되지 않는 이슈를 갖고 있음
  • Loading branch information
donggi-lee-bit authored Apr 21, 2022
1 parent ff0bf27 commit 8370c1a
Show file tree
Hide file tree
Showing 8 changed files with 228 additions and 13 deletions.
49 changes: 48 additions & 1 deletion BE/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,50 @@ plugins {
id 'org.springframework.boot' version '2.6.6'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
id 'org.asciidoctor.jvm.convert' version "3.3.2"
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
asciidoctorExtentions
}

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

test {
outputs.dir snippetsDir
}

asciidoctor {
inputs.dir snippetsDir
dependsOn test
}

bootJar {
dependsOn asciidoctor
copy {
from "${asciidoctor.outputDir}"
into 'src/main/resources/static/docs'
}
}

// docs html 에 파일 복사
task copyDocument(type: Copy) {
dependsOn asciidoctor

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

build {
dependsOn copyDocument
}

repositories {
mavenCentral()
}
Expand All @@ -19,6 +57,10 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc:2.6.4'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'

// lombok
implementation 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'

// DB
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'mysql:mysql-connector-java:8.0.28'
Expand All @@ -28,8 +70,13 @@ dependencies {
implementation 'io.springfox:springfox-swagger2:2.9.2'
implementation 'io.springfox:springfox-swagger-ui:2.9.2'

// Spring Rest Docs
asciidoctorExtentions 'org.springframework.restdocs:spring-restdocs-asciidoctor'
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'

// test
testImplementation 'org.springframework.boot:spring-boot-starter-test:2.5.5'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'io.rest-assured:rest-assured'
}

tasks.named('test') {
Expand Down
18 changes: 18 additions & 0 deletions BE/src/docs/asciidoc/api-doc.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
= Spring REST Docs
:toc: left
:toclevels: 2
:sectlinks:

[[resources-post]]
== Post

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

==== HTTP request

include::{snippets}/전체 기획전 데이터/http-request.adoc[]

==== HTTP response

include::{snippets}/전체 기획전 데이터/http-response.adoc[]
2 changes: 1 addition & 1 deletion BE/src/main/java/com/example/be/controller/ApiError.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class ApiError {
this(throwable.getMessage(), status);
}

ApiError(String message, HttpStatus status) {
public ApiError(String message, HttpStatus status) {
this.message = message;
this.status = status.value();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
package com.example.be.controller.dish;

import static com.example.be.controller.ApiResult.OK;

import com.example.be.controller.ApiResult;
import com.example.be.controller.dish.dto.PlanningDataRequest;
import com.example.be.service.dish.DishService;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

import static com.example.be.controller.ApiResult.OK;

@RestController
@RequestMapping("/api/dishes")
public class DishController {
Expand All @@ -23,10 +22,16 @@ public DishController(DishService dishService) {
}

@GetMapping
public ApiResult<List<PlanningDataRequest>> getPlanningData() {
return OK(dishService.getPlanningData());
public List<PlanningDataRequest> getPlanningData() {
return dishService.getPlanningData();
}


// @GetMapping
// public ApiResult<List<PlanningDataRequest>> getPlanningData() {
// return OK(dishService.getPlanningData());
// }

@GetMapping("{id}")
public ApiResult<DishDetail> getDishDetail(@PathVariable("id") Long id) {
return OK(new DishDetail(dishService.getDishDetail(id)));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
package com.example.be.service.dish;

import com.example.be.controller.ApiResult;
import com.example.be.controller.dish.DishDetail;
import com.example.be.controller.dish.dto.PlanningDataRequest;
import com.example.be.controller.exception.UserTypeException;
import com.example.be.domain.dish.Dish;
import com.example.be.repository.dish.DishReadRepository;
import com.example.be.repository.dish.DishRepository;
import java.util.List;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class DishService {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.example.be.controller.dish;

import static org.mockito.BDDMockito.given;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
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.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import com.example.be.controller.dish.dto.PlanningDataRequest;
import com.example.be.domain.dish.Badge;
import com.example.be.domain.dish.DeliveryType;
import com.example.be.domain.dish.DishStatus;
import com.example.be.service.dish.DishService;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
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.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.restdocs.RestDocumentationExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

@AutoConfigureMockMvc
@AutoConfigureRestDocs

@ExtendWith(RestDocumentationExtension.class)
@WebMvcTest(DishController.class)
@DisplayName("API /api/dishes/* 컨트롤러 계층 단위 테스트")
class DishControllerTest {

@Autowired
private MockMvc mockMvc;

@MockBean
private DishService dishService;

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

@Test
void getPlanningDataTest() throws Exception {
List<PlanningDataRequest> dishes = createTestData();

given(dishService.getPlanningData())
.willReturn(dishes);

ResultActions result = mockMvc.perform(MockMvcRequestBuilders.get("/api/dishes"));

result
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andDo(document("sidedish",
responseFields(
fieldWithPath("[].title").description("title 제목 작성"),
fieldWithPath("[].description").description("description 본문 작성").optional(),
fieldWithPath("[].dishId").description("1"),
fieldWithPath("[].name").description("이름"),
fieldWithPath("[].normalPrice").description("10000"),
fieldWithPath("[].salePrice").description("9000"),
fieldWithPath("[].badge").description("NONE"),
fieldWithPath("[].deliveryType").description("NONE"),
fieldWithPath("[].thumbnail").description("naver.com"),
fieldWithPath("[].dishStatus").description("OUT_OF_STOCK"),
fieldWithPath("[].categoryId").description("1")
)
));

}

private List<PlanningDataRequest> createTestData() {
List<PlanningDataRequest> dishes = new ArrayList<>();
dishes.add(0,
new PlanningDataRequest(1L, "이름", "설명", new BigDecimal(10000), new BigDecimal(9000),
Badge.NONE, DeliveryType.NONE, "naver.com", DishStatus.OUT_OT_STOCK, 1L,
"타이틀"));
dishes.add(1,
new PlanningDataRequest(2L, "이름2", "설명2", new BigDecimal(100002), new BigDecimal(90002),
Badge.NONE, DeliveryType.NONE, "naver.com222", DishStatus.OUT_OT_STOCK, 2L,
"타이틀2"));


return dishes;
}
}
21 changes: 21 additions & 0 deletions BE/src/test/resources/application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
spring:
datasource:
driverClassName: org.h2.Driver
url: jdbc:h2:mem:testdb
username: sa
sql:
init:
mode: always
schema-locations: classpath:testDB/schema.sql
# data-locations: classpath:testDB/data.sql
h2:
console:
enabled: true
path: /h2-console
mvc:
pathmatch:
matching-strategy: ant_path_matcher

logging:
level:
web: DEBUG
30 changes: 30 additions & 0 deletions BE/src/test/resources/testDB/schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
DROP TABLE IF EXISTS dish;
CREATE TABLE dish
(
dish_id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NULL,
description VARCHAR(255) NULL,
normal_price DECIMAL NULL,
sale_price DECIMAL NULL,
badge VARCHAR(255) NULL,
delivery_type VARCHAR(255) NULL,
thumbnail VARCHAR(255) NULL,
category_id BIGINT NOT NULL,
dish_status VARCHAR(255) NULL
);


DROP TABLE IF EXISTS category;
CREATE TABLE category
(
category_id BIGINT NOT NULL PRIMARY KEY,
title VARCHAR(255)
);

DROP TABLE IF EXISTS users;
CREATE TABLE users
(
user_id BIGINT NOT NULL PRIMARY KEY,
login_id BIGINT NOT NULL,
password VARCHAR(60) NOT NULL
);

0 comments on commit 8370c1a

Please sign in to comment.