Skip to content

Commit

Permalink
[KAN-123] feat(functionaltest): 상품 기능 테스트 구현 및 api 명세 완료
Browse files Browse the repository at this point in the history
  • Loading branch information
rlatkd committed Jul 8, 2024
1 parent 2c4ff21 commit 7d06301
Show file tree
Hide file tree
Showing 15 changed files with 584 additions and 781 deletions.
56 changes: 31 additions & 25 deletions server/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ plugins {
id 'java'
id 'org.springframework.boot' version '3.3.1'
id 'io.spring.dependency-management' version '1.1.5'
id 'checkstyle'
id 'org.asciidoctor.jvm.convert' version '3.3.2' //1
// id 'checkstyle'
id 'org.asciidoctor.jvm.convert' version '3.3.2' // REST Docs
}

group = 'kr.or.kosa'
Expand All @@ -19,15 +19,15 @@ configurations {
compileOnly {
extendsFrom annotationProcessor
}
asciidoctorExtensions //2
asciidoctorExtensions // REST Docs
}

repositories {
mavenCentral()
}

ext {
set('snippetsDir', file("build/generated-snippets")) //3
set('snippetsDir', file("build/generated-snippets")) // REST Docs
}

dependencies {
Expand All @@ -44,35 +44,41 @@ dependencies {
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

//4
// REST Docs
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
asciidoctorExtensions 'org.springframework.restdocs:spring-restdocs-asciidoctor'
}

test {
useJUnitPlatform()
outputs.dir snippetsDir
outputs.dir snippetsDir // REST Docs
}

// REST Docs
asciidoctor {
inputs.dir snippetsDir
configurations 'asciidoctorExtensions'
dependsOn test
// source를 지정하면 특정 adoc만 HTML로 만듬
sources {
include("**/*.adoc")
}
// 경로를 baseDir로 맞춰줌
baseDirFollowsSourceFile()
}

// REST Docs
task copyDocs(type: Copy) {
dependsOn asciidoctor
from "${asciidoctor.outputDir}"
into "src/main/resources/static/docs" // src/main/resources/static/docs로 복사
}

// REST Docs
build {
dependsOn copyDocs
}
Expand All @@ -96,22 +102,22 @@ clean.doLast {


// Lint
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8'
}

tasks.withType(Checkstyle).configureEach {
mustRunAfter 'compileJava'
reports {
xml.required = false
html.required = true
}
}

checkstyle {
configFile = file("config/checkstyle/naver-checkstyle-rules.xml")
configProperties = ["suppressionFile": "config/checkstyle/naver-checkstyle-suppressions.xml"]
sourceSets = [sourceSets.main] // CompileQuerydsl 오류 해결
}

checkstyleMain.source = fileTree('src/main/java')
//tasks.withType(JavaCompile).configureEach {
// options.encoding = 'UTF-8'
//}
//
//tasks.withType(Checkstyle).configureEach {
// mustRunAfter 'compileJava'
// reports {
// xml.required = false
// html.required = true
// }
//}
//
//checkstyle {
// configFile = file("config/checkstyle/naver-checkstyle-rules.xml")
// configProperties = ["suppressionFile": "config/checkstyle/naver-checkstyle-suppressions.xml"]
// sourceSets = [sourceSets.main] // CompileQuerydsl 오류 해결
//}
//
//checkstyleMain.source = fileTree('src/main/java')
109 changes: 106 additions & 3 deletions server/src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,110 @@ made by Sanghun.Kim
:toc: left
:toclevels: 4
:sectlinks:
:operation-http-request-title: Request
:operation-http-response-title: Response
:operation-http-request-title: REQUEST
:operation-http-response-title: RESPONSE

include::{docdir}/products/products.adoc[]
[[POST-API]]
== 1. 상품

=== 1.1. 상품 목록 조회

.Request Header Parameter
|===
|파라미터 |타입 |필수여부 |설명
|Authorization |String |필수 |ACCESS_TOKEN
|X-CSRF |String |필수 |CSRF_TOKEN
|===

.Request Query Parameter
|===
|파라미터 |타입 |필수여부 |설명
|page |Integer|필수 |페이지 번호
|offset |Integer|필수 |페이지당 오프셋
|sort |String|선택 |정렬 기준
|name |String|선택 |상품명으로 검색
|price |double|선택 |금액으로 검색
|contractCount |Integer|선택 |계약수로 검색
|createdAt |String|선택 |생성시기로 검색
|memo |String|선택 |비고로 검색
|===

operation::findAllProductByCondition[snippets='http-request,http-response']

=== 1.2. 상품 등록

.Request Header Parameter
|===
|파라미터 |타입 |필수여부 |설명
|Authorization |String |필수 |ACCESS_TOKEN
|X-CSRF |String |필수 |CSRF_TOKEN
|===

.Request Body Parameter
|===
|파라미터 |타입 |필수여부 |설명
|name |String|필수 |상품명
|price |double|필수 |금액
|memo |Stirng|필수 |비고
|===

operation::saveProduct[snippets='http-request,http-response']

=== 1.3. 상품 상세 조회

.Request Header Parameter
|===
|파라미터 |타입 |필수여부 |설명
|Authorization |String |필수 |ACCESS_TOKEN
|X-CSRF |String |필수 |CSRF_TOKEN
|===

.Request Path Parameter
|===
|파라미터 |타입 |필수여부 |설명
|PRODUCT_ID |Long|필수 |상품번호
|===

operation::findProductById[snippets='http-request,http-response']

=== 1.4. 상품 수정

.Request Header Parameter
|===
|파라미터 |타입 |필수여부 |설명
|Authorization |String |필수 |ACCESS_TOKEN
|X-CSRF |String |필수 |CSRF_TOKEN
|===

.Request Path Parameter
|===
|파라미터 |타입 |필수여부 |설명
|PRODUCT_ID |Long|필수 |상품번호
|===

.Request Body Parameter
|===
|파라미터 |타입 |필수여부 |설명
|name |String|선택 |상품명
|price |double|선택 |금액
|notes |Stirng|선택 |비고
|===

operation::updateProduct[snippets='http-request,http-response']

=== 1.5. 상품 삭제

.Request Header
|===
|파라미터 |타입 |필수여부 |설명
|Authorization |String |필수 |인증 키
|===

.Request Path Parameter
|===
|파라미터 |타입 |필수여부 |설명
|PRODUCT_ID |Long|필수 |상품번호
|===


operation::deleteProduct[snippets='http-request,http-response']
17 changes: 0 additions & 17 deletions server/src/docs/asciidoc/products/products-get.adoc

This file was deleted.

4 changes: 0 additions & 4 deletions server/src/docs/asciidoc/products/products.adoc

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package kr.or.kosa.cmsplusmain.test.domain.product.controller;

import kr.or.kosa.cmsplusmain.test.domain.product.dto.TProductDto;
import kr.or.kosa.cmsplusmain.test.domain.product.dto.TProductFindAllByConditionRes;
import kr.or.kosa.cmsplusmain.test.domain.product.dto.TProductSaveReq;
import kr.or.kosa.cmsplusmain.test.domain.product.dto.TProductUpdateReq;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/api/v1/vendor/product")
public class TProductController {

// 초기화
public TProductController() {
initData();
}

// 상품 리스트
private final List<TProductDto> productList = new ArrayList<>();

// 테스트용 더미 데이터 생성 (조회시 등록하지않으나 있다고 가정하고 하나 넣어야함 | 실제 DB 연동으로 대체해야 함)
public void initData() {

// 테스트에서 중복 실행 방지 초기화
productList.clear();
List<TProductDto> initData = List.of(
new TProductDto(1L, 1001L, "상품 조회용 데이터1", 10.0, 10, "2024-01-01 11:11:11", "Null", "Null", "비고 1", "STATUS1"),
new TProductDto(2L, 1002L, "상품 조회용 데이터2", 20.0, 22, "2024-01-02 11:11:11", "2024-01-01 11:11:11", "2024-01-01", "비고 2", "STATUS2")
);

// 더미데이터 세팅
productList.addAll(initData);

}

// 상품 목록 조회
@GetMapping
public TProductFindAllByConditionRes findAllProductByCondition(@RequestParam int page, @RequestParam int offset) {

// /api/v1/vendor/products?page=1&offset=10
// 페이지네이션 이외에 정렬, 필터, 검색 기능 염두해야 함
// 페이지네이션과 정렬, 필터링 기능을 구현해야 하지만 여기서는 간단히 더미 데이터를 반환
List<TProductDto> data = new ArrayList<>(productList);

// Pagination (실제 로직에 따라 계산 필요)
int totalPage = 100;
int totalCount = 1000;

TProductFindAllByConditionRes tProductFindAllByConditionRes = new TProductFindAllByConditionRes();
tProductFindAllByConditionRes.setPage(page);
tProductFindAllByConditionRes.setOffset(offset);
tProductFindAllByConditionRes.setTotalPage(totalPage);
tProductFindAllByConditionRes.setTotalCount(totalCount);
tProductFindAllByConditionRes.setData(data);

return tProductFindAllByConditionRes;

}

// 상품 등록
@PostMapping
public TProductDto saveProduct(@RequestBody TProductSaveReq tProductSaveReq) {

// 새로 등록할 상품
TProductDto newProduct = new TProductDto(
tProductSaveReq.getId(),
tProductSaveReq.getVendorId(),
tProductSaveReq.getName(),
tProductSaveReq.getPrice(),
0, // 이건 DB에서 알아서 할듯
tProductSaveReq.getCreatedDateTime(),
null, // 이건 DB에서 알아서 할듯
null, // 이건 DB에서 알아서 할듯
tProductSaveReq.getMemo(),
"STATUS1" // 이건 DB에서 알아서 할듯
);

productList.add(newProduct);

return newProduct;
}

// 상품 상세 조회
@GetMapping("/{PRODUCT_ID}")
public TProductDto findProductById(@PathVariable("PRODUCT_ID") Long productId) {

// 람다식으로 해당 상품아이디 매핑
// 실제 코드에선 DTO를 분리해서 해야하나 현재 기본 TProductDto에 데이터를 강제로 주입시키기 때문에 애로사항이 있음
TProductDto product = productList.stream()
.filter(p -> p.getId().equals(productId))
.findFirst()
.orElse(null);

return product;
}

// 상품 수정
@PutMapping("/{PRODUCT_ID}")
public TProductDto updateProduct(@PathVariable("PRODUCT_ID") Long productId, @RequestBody TProductUpdateReq tProductUpdateReq) {

// 람다식으로 해당 상품아이디 매핑
TProductDto updatedProduct = productList.stream()
.filter(p -> p.getId().equals(productId))
.findFirst()
.orElse(null);

// 상품 수정할 정보
updatedProduct.setName(tProductUpdateReq.getName());
updatedProduct.setPrice(tProductUpdateReq.getPrice());
updatedProduct.setMemo(tProductUpdateReq.getMemo());
updatedProduct.setUpdatedDateTime("2024-01-01 11:11:11"); // 이건 DB에서 알아서 할듯

return updatedProduct;
}

// 상품 삭제
@DeleteMapping("/{PRODUCT_ID}")
public TProductDto deleteProduct(@PathVariable("PRODUCT_ID") Long productId) {

// 람다식으로 해당 상품아이디 매핑
TProductDto product = productList.stream()
.filter(p -> p.getId().equals(productId))
.findFirst()
.orElse(null);

// 실제 삭제 대신 상태 업데이트
product.setStatus("DELETED");
product.setDeletedDate("2024-01-01"); // 이건 DB에서 알아서 할듯

return product;
}

}
Loading

0 comments on commit 7d06301

Please sign in to comment.