From 13085f875bc19c227991a2754f1b537d148af6c6 Mon Sep 17 00:00:00 2001 From: 0BVer Date: Wed, 4 May 2022 23:51:02 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat=20:=20Post=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20=ED=95=84=EB=93=9C=EB=A5=BC=20=EC=B9=B4=EB=A9=9C=20?= =?UTF-8?q?=EC=BC=80=EC=9D=B4=EC=8A=A4=EB=A1=9C=20=EB=B3=80=EA=B2=BD,=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=20=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/post/domain/entity/Post.java | 28 +++++++++++++------ .../backend/domain/post/dto/PostRequest.java | 10 +++---- .../backend/domain/post/dto/PostResponse.java | 12 ++++---- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/Post.java b/backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/Post.java index ef5553b..c1586cb 100644 --- a/backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/Post.java +++ b/backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/Post.java @@ -1,5 +1,6 @@ package com.hjjang.backend.domain.post.domain.entity; +import com.hjjang.backend.domain.user.entity.User; import lombok.*; import org.hibernate.annotations.ColumnDefault; import org.hibernate.annotations.DynamicInsert; @@ -11,40 +12,49 @@ @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) @DynamicInsert -@Table(schema = "post") +@Table(name = "post") @Entity public class Post { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; -// @ManyToOne -// @JoinColumn(name = "user_id") -// private User user; + @ManyToOne + @JoinColumn(name = "user_id") + private User user; // @ManyToOne // @JoinColumn(name = "image_id") // private Image image; + @Column(name = "title", nullable = false) private String title; + + @Column(name = "content", nullable = false) private String content; - private Integer item_price; + @Column(name = "item_price", nullable = false) + private int itemPrice; @ColumnDefault("0") - private Integer views = 0; + @Column(name = "views", nullable = false) + private int views = 0; @ColumnDefault("0") - private Integer interest_number = 0; + @Column(name = "interest_number", nullable = false) + private int interestNumber = 0; @ColumnDefault("0") - private Integer chat_number = 0; + @Column(name = "chat_number", nullable = false) + private int chatNumber = 0; @ColumnDefault("'false'") - private String is_sale_completion = "false"; + @Column(name = "is_sale_completion", nullable = false) + private String isSaleCompletion = "false"; @ColumnDefault("false") + @Column(name = "removed", nullable = false) private boolean removed = false; public void removePost() { diff --git a/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostRequest.java b/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostRequest.java index 6cffcc1..2272b66 100644 --- a/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostRequest.java +++ b/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostRequest.java @@ -1,6 +1,7 @@ package com.hjjang.backend.domain.post.dto; import com.hjjang.backend.domain.post.domain.entity.Post; +import com.hjjang.backend.domain.user.entity.User; import lombok.*; import javax.validation.constraints.NotEmpty; @@ -10,7 +11,6 @@ @AllArgsConstructor @RequiredArgsConstructor public class PostRequest { - @NotEmpty private String title; @@ -18,15 +18,15 @@ public class PostRequest { private String content; @NotEmpty - private String price; + private int price; - public Post toEntity() { + public Post toEntity(User user) { return Post.builder() -// .user(null) + .user(user) // .image(null) .title(this.title) .content(this.content) - .item_price(Integer.valueOf(this.price)) + .itemPrice(this.price) .build(); } } diff --git a/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostResponse.java b/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostResponse.java index 39681cd..df198b0 100644 --- a/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostResponse.java +++ b/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostResponse.java @@ -12,7 +12,7 @@ public class PostResponse { private Long id; -// private Long user_id; + private Long user_id; // private Long image_id; @@ -35,15 +35,15 @@ public class PostResponse { public static PostResponse of(Post post) { return PostResponse.builder() .id(post.getId()) -// .user_id(post.getUser().getId()) + .user_id(post.getUser().getId()) // .image_id(post.getImage().getId()) .title(post.getTitle()) .content(post.getContent()) - .item_price(post.getItem_price()) + .item_price(post.getItemPrice()) .views(post.getViews()) - .interest_number(post.getInterest_number()) - .chat_number(post.getChat_number()) - .is_sale_completion(post.getIs_sale_completion()) + .interest_number(post.getInterestNumber()) + .chat_number(post.getChatNumber()) + .is_sale_completion(post.getIsSaleCompletion()) .removed(post.isRemoved()) .build(); } From 7879802a43c7aa27e6a38557a8d5f622c8059d25 Mon Sep 17 00:00:00 2001 From: 0BVer Date: Wed, 4 May 2022 23:51:27 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat=20:=20=EA=B8=B0=EC=A1=B4=20api?= =?UTF-8?q?=EC=97=90=20ApiResponse=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/controller/PostController.java | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/backend/src/main/java/com/hjjang/backend/domain/post/controller/PostController.java b/backend/src/main/java/com/hjjang/backend/domain/post/controller/PostController.java index 00e504f..91beac9 100644 --- a/backend/src/main/java/com/hjjang/backend/domain/post/controller/PostController.java +++ b/backend/src/main/java/com/hjjang/backend/domain/post/controller/PostController.java @@ -3,6 +3,8 @@ import com.hjjang.backend.domain.post.dto.PostRequest; import com.hjjang.backend.domain.post.dto.PostResponse; import com.hjjang.backend.domain.post.service.PostServiceImpl; +import com.hjjang.backend.global.dto.ApiResponse; +import com.hjjang.backend.global.util.UserUtil; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -18,37 +20,44 @@ public class PostController { private final PostServiceImpl postService; + private final UserUtil userUtil; @PostMapping - public ResponseEntity createItem(@Validated @RequestBody PostRequest postRequest) { + public ResponseEntity createItem(@Validated @RequestBody PostRequest postRequest) { return ResponseEntity.ok( - PostResponse.of( - postService.save( - postRequest.toEntity() + ApiResponse.success("createItem", + PostResponse.of( + postService.save( + postRequest.toEntity( + userUtil.getLoginUserByToken() + ) + ) ) ) ); } @GetMapping - public ResponseEntity> findAllItem() { - return ResponseEntity.ok(postService - .findAll() - .stream() - .map(PostResponse::of) - .collect(Collectors.toList()) + public ResponseEntity findAllItem() { + return ResponseEntity.ok( + ApiResponse.success("findAllItem", postService + .findAll() + .stream() + .map(PostResponse::of) + .collect(Collectors.toList()) + ) ); } @GetMapping("/{id}") - public ResponseEntity findOneItem(@PathVariable Long id) { - return ResponseEntity.ok(PostResponse.of(postService.findOneById(id))); + public ResponseEntity findOneItem(@PathVariable Long id) { + return ResponseEntity.ok(ApiResponse.success("findOneItem", PostResponse.of(postService.findOneById(id)))); } @DeleteMapping("/{id}") - public ResponseEntity deleteOneItem(@PathVariable Long id) { + public ResponseEntity deleteOneItem(@PathVariable Long id) { postService.deleteOneById(id); - return ResponseEntity.ok(HttpStatus.ACCEPTED); + return ResponseEntity.ok(ApiResponse.success("deleteOneItem", HttpStatus.ACCEPTED)); } From c6f5b53592a63cee0be07b9b07122ac48b621ff9 Mon Sep 17 00:00:00 2001 From: 0BVer Date: Fri, 6 May 2022 00:14:48 +0900 Subject: [PATCH 3/6] =?UTF-8?q?debug=20:=20requestDto=20=EB=B2=84=EA=B7=B8?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/hjjang/backend/domain/post/dto/PostRequest.java | 7 ++++--- frontend/src/auth/OAuth.js | 3 +-- package-lock.json | 6 ------ 3 files changed, 5 insertions(+), 11 deletions(-) delete mode 100644 package-lock.json diff --git a/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostRequest.java b/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostRequest.java index 2272b66..fc9061b 100644 --- a/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostRequest.java +++ b/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostRequest.java @@ -5,19 +5,20 @@ import lombok.*; import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; @Getter @Setter @AllArgsConstructor @RequiredArgsConstructor public class PostRequest { - @NotEmpty + @NotNull private String title; - @NotEmpty + @NotNull private String content; - @NotEmpty + @NotNull private int price; public Post toEntity(User user) { diff --git a/frontend/src/auth/OAuth.js b/frontend/src/auth/OAuth.js index 27ca6ed..296c180 100644 --- a/frontend/src/auth/OAuth.js +++ b/frontend/src/auth/OAuth.js @@ -2,5 +2,4 @@ export const ACCESS_TOKEN = "accessToken"; export const API_BASE_URL = `${process.env.REACT_APP_HOST}`; export const OAUTH2_REDIRECT_URI = `${API_BASE_URL}/oauth2/redirect`; export const SERVER_BASE_URL = `${process.env.REACT_APP_SERVER_HOST}`; -export const KAKAO_AUTH_URL = `${SERVER_BASE_URL}/oauth2/authorization/kakao?redirect_uri=${OAUTH2_REDIRECT_URI}`; -가 \ No newline at end of file +export const KAKAO_AUTH_URL = `${SERVER_BASE_URL}/oauth2/authorization/kakao?redirect_uri=${OAUTH2_REDIRECT_URI}`; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index c357ef8..0000000 --- a/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "bauction", - "lockfileVersion": 2, - "requires": true, - "packages": {} -} From fe4d541d44d3faa7c62cb318850feae1106d0ab6 Mon Sep 17 00:00:00 2001 From: 0BVer Date: Mon, 9 May 2022 23:00:44 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat=20:=20Post=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/build.gradle | 4 ++ .../post/controller/PostController.java | 54 ++++++++++++------- .../domain/post/domain/entity/Post.java | 54 ++++++++++++------- .../post/domain/entity/PostDefaultValue.java | 15 ++++++ .../domain/post/domain/entity/PostState.java | 15 ++++++ .../backend/domain/post/dto/PostMapper.java | 35 ++++++++++++ .../backend/domain/post/dto/PostRequest.java | 33 ------------ .../domain/post/dto/PostRequestDto.java | 19 +++++++ .../backend/domain/post/dto/PostResponse.java | 50 ----------------- .../domain/post/dto/PostResponseDto.java | 34 ++++++++++++ .../domain/post/service/PostServiceImpl.java | 12 ++++- .../backend/domain/user/entity/User.java | 3 +- .../user/exception/UserNotMatchException.java | 21 ++++++++ .../post/service/PostServiceImplTest.java | 4 ++ backend/src/test/resources/application.yml | 16 ++++++ 15 files changed, 246 insertions(+), 123 deletions(-) create mode 100644 backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/PostDefaultValue.java create mode 100644 backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/PostState.java create mode 100644 backend/src/main/java/com/hjjang/backend/domain/post/dto/PostMapper.java delete mode 100644 backend/src/main/java/com/hjjang/backend/domain/post/dto/PostRequest.java create mode 100644 backend/src/main/java/com/hjjang/backend/domain/post/dto/PostRequestDto.java delete mode 100644 backend/src/main/java/com/hjjang/backend/domain/post/dto/PostResponse.java create mode 100644 backend/src/main/java/com/hjjang/backend/domain/post/dto/PostResponseDto.java create mode 100644 backend/src/main/java/com/hjjang/backend/domain/user/exception/UserNotMatchException.java create mode 100644 backend/src/test/java/com/hjjang/backend/domain/post/service/PostServiceImplTest.java create mode 100644 backend/src/test/resources/application.yml diff --git a/backend/build.gradle b/backend/build.gradle index e66b88a..6f96ced 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -42,13 +42,17 @@ dependencies { developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'io.micrometer:micrometer-registry-prometheus' runtimeOnly 'mysql:mysql-connector-java' + annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' annotationProcessor 'org.projectlombok:lombok' + + testImplementation 'com.h2database:h2' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.batch:spring-batch-test' testImplementation 'org.springframework.kafka:spring-kafka-test' testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' testImplementation 'org.springframework.security:spring-security-test' + implementation 'org.springdoc:springdoc-openapi-ui:1.6.6' //jwt 관련 의존성 implementation 'io.jsonwebtoken:jjwt-api:0.11.2' diff --git a/backend/src/main/java/com/hjjang/backend/domain/post/controller/PostController.java b/backend/src/main/java/com/hjjang/backend/domain/post/controller/PostController.java index 91beac9..72cbec6 100644 --- a/backend/src/main/java/com/hjjang/backend/domain/post/controller/PostController.java +++ b/backend/src/main/java/com/hjjang/backend/domain/post/controller/PostController.java @@ -1,49 +1,53 @@ package com.hjjang.backend.domain.post.controller; -import com.hjjang.backend.domain.post.dto.PostRequest; -import com.hjjang.backend.domain.post.dto.PostResponse; +import com.hjjang.backend.domain.post.dto.PostMapper; +import com.hjjang.backend.domain.post.dto.PostRequestDto; +import com.hjjang.backend.domain.post.dto.PostResponseDto; import com.hjjang.backend.domain.post.service.PostServiceImpl; import com.hjjang.backend.global.dto.ApiResponse; import com.hjjang.backend.global.util.UserUtil; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.List; import java.util.stream.Collectors; +import static org.springframework.http.HttpStatus.*; +import static org.springframework.http.ResponseEntity.*; + @RequiredArgsConstructor @RequestMapping("/api/posts") @RestController public class PostController { private final PostServiceImpl postService; + private final PostMapper postMapper; private final UserUtil userUtil; @PostMapping - public ResponseEntity createItem(@Validated @RequestBody PostRequest postRequest) { - return ResponseEntity.ok( - ApiResponse.success("createItem", - PostResponse.of( - postService.save( - postRequest.toEntity( - userUtil.getLoginUserByToken() + public ResponseEntity createItem(@Validated @RequestBody PostRequestDto postRequestDto) { + return status(CREATED) + .body(ApiResponse.success( + "createItem", + postMapper.fromEntity( + postService.save( + postMapper.toEntity( + postRequestDto, userUtil.getLoginUserByToken() + ) ) ) ) - ) - ); + ); } @GetMapping public ResponseEntity findAllItem() { - return ResponseEntity.ok( + return ok( ApiResponse.success("findAllItem", postService .findAll() .stream() - .map(PostResponse::of) + .map(postMapper::fromEntity) .collect(Collectors.toList()) ) ); @@ -51,14 +55,26 @@ public ResponseEntity findAllItem() { @GetMapping("/{id}") public ResponseEntity findOneItem(@PathVariable Long id) { - return ResponseEntity.ok(ApiResponse.success("findOneItem", PostResponse.of(postService.findOneById(id)))); + return ok(ApiResponse.success("findOneItem", postMapper.fromEntity(postService.findOneById(id)))); + } + + @PutMapping("/{id}") + public ResponseEntity putOneItem(@PathVariable Long id, @Validated @RequestBody PostRequestDto postRequestDto) { + return status(CREATED) + .body(ApiResponse.success( + "updatePutOneItem", + postMapper.fromEntity( + postService.updateOneById( + id, postRequestDto, userUtil.getLoginUserByToken() + ) + ) + ) + ); } @DeleteMapping("/{id}") public ResponseEntity deleteOneItem(@PathVariable Long id) { postService.deleteOneById(id); - return ResponseEntity.ok(ApiResponse.success("deleteOneItem", HttpStatus.ACCEPTED)); + return ok(ApiResponse.success("deleteOneItem", ACCEPTED)); } - - } diff --git a/backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/Post.java b/backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/Post.java index c1586cb..b3bfcdc 100644 --- a/backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/Post.java +++ b/backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/Post.java @@ -1,17 +1,20 @@ package com.hjjang.backend.domain.post.domain.entity; +import com.hjjang.backend.domain.post.dto.PostRequestDto; import com.hjjang.backend.domain.user.entity.User; import lombok.*; -import org.hibernate.annotations.ColumnDefault; -import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.CreationTimestamp; import javax.persistence.*; +import java.time.LocalDateTime; + +import static com.hjjang.backend.domain.post.domain.entity.PostDefaultValue.*; @Getter -@Builder +//@Builder @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) -@DynamicInsert +//@DynamicInsert @Table(name = "post") @Entity public class Post { @@ -23,41 +26,54 @@ public class Post { @JoinColumn(name = "user_id") private User user; -// @ManyToOne -// @JoinColumn(name = "image_id") -// private Image image; - @Column(name = "title", nullable = false) private String title; - @Column(name = "content", nullable = false) private String content; @Column(name = "item_price", nullable = false) private int itemPrice; - @ColumnDefault("0") +// @ColumnDefault("0") @Column(name = "views", nullable = false) - private int views = 0; + private int views = DEFAULT_VIEWS; - @ColumnDefault("0") +// @ColumnDefault("0") @Column(name = "interest_number", nullable = false) - private int interestNumber = 0; + private int interestNumber = DEFAULT_INTEREST_NUMBER; - @ColumnDefault("0") +// @ColumnDefault("0") @Column(name = "chat_number", nullable = false) - private int chatNumber = 0; + private int chatNumber = DEFAULT_CHAT_NUMBER; - @ColumnDefault("'false'") + @Enumerated(EnumType.STRING) @Column(name = "is_sale_completion", nullable = false) - private String isSaleCompletion = "false"; + private PostState isSaleCompletion = DEFAULT_IS_SALE_COMPLETION; - @ColumnDefault("false") +// @ColumnDefault("false") @Column(name = "removed", nullable = false) - private boolean removed = false; + private boolean removed = DEFAULT_REMOVED; + + @CreationTimestamp + private LocalDateTime time; + + @Builder + public Post(User user, String title, String content, int itemPrice) { + this.user = user; + this.title = title; + this.content = content; + this.itemPrice = itemPrice; + } public void removePost() { this.removed = true; } + + public Post update(PostRequestDto postRequestDto) { + this.title = postRequestDto.getTitle(); + this.content = postRequestDto.getContent(); + this.itemPrice = postRequestDto.getPrice(); + return this; + } } diff --git a/backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/PostDefaultValue.java b/backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/PostDefaultValue.java new file mode 100644 index 0000000..b665a8d --- /dev/null +++ b/backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/PostDefaultValue.java @@ -0,0 +1,15 @@ +package com.hjjang.backend.domain.post.domain.entity; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class PostDefaultValue { + public static final int DEFAULT_VIEWS = 0; + public static final int DEFAULT_INTEREST_NUMBER = 0; + public static final int DEFAULT_CHAT_NUMBER = 0; + public static final PostState DEFAULT_IS_SALE_COMPLETION = PostState.SALE; + public static final boolean DEFAULT_REMOVED = false; +} diff --git a/backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/PostState.java b/backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/PostState.java new file mode 100644 index 0000000..7a75b43 --- /dev/null +++ b/backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/PostState.java @@ -0,0 +1,15 @@ +package com.hjjang.backend.domain.post.domain.entity; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum PostState { + SALE("판매중"), + RESERVED("예약중"), + SOLD("판매완료"), + ; + + final String state; +} diff --git a/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostMapper.java b/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostMapper.java new file mode 100644 index 0000000..37b9602 --- /dev/null +++ b/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostMapper.java @@ -0,0 +1,35 @@ +package com.hjjang.backend.domain.post.dto; + +import com.hjjang.backend.domain.post.domain.entity.Post; +import com.hjjang.backend.domain.user.entity.User; +import org.springframework.stereotype.Service; + +@Service +public class PostMapper { + + public Post toEntity(PostRequestDto postRequestDto, User user) { + return Post.builder() + .user(user) + .title(postRequestDto.getTitle()) + .content(postRequestDto.getContent()) + .itemPrice(postRequestDto.getPrice()) + .build(); + } + + public PostResponseDto fromEntity(Post post) { + return PostResponseDto.builder() + .id(post.getId()) + .user_id(post.getUser().getId()) + .title(post.getTitle()) + .content(post.getContent()) + .item_price(post.getItemPrice()) + .views(post.getViews()) + .interest_number(post.getInterestNumber()) + .chat_number(post.getChatNumber()) + .is_sale_completion(post.getIsSaleCompletion().getState()) + .removed(post.isRemoved()) + .time(post.getTime().toString()) + .build(); + } + +} diff --git a/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostRequest.java b/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostRequest.java deleted file mode 100644 index fc9061b..0000000 --- a/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostRequest.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.hjjang.backend.domain.post.dto; - -import com.hjjang.backend.domain.post.domain.entity.Post; -import com.hjjang.backend.domain.user.entity.User; -import lombok.*; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; - -@Getter -@Setter -@AllArgsConstructor -@RequiredArgsConstructor -public class PostRequest { - @NotNull - private String title; - - @NotNull - private String content; - - @NotNull - private int price; - - public Post toEntity(User user) { - return Post.builder() - .user(user) -// .image(null) - .title(this.title) - .content(this.content) - .itemPrice(this.price) - .build(); - } -} diff --git a/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostRequestDto.java b/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostRequestDto.java new file mode 100644 index 0000000..ba52543 --- /dev/null +++ b/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostRequestDto.java @@ -0,0 +1,19 @@ +package com.hjjang.backend.domain.post.dto; + +import lombok.*; + +import javax.validation.constraints.NotNull; + +@Data +@Builder +@AllArgsConstructor +public class PostRequestDto { + @NotNull + private String title; + + @NotNull + private String content; + + @NotNull + private int price; +} diff --git a/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostResponse.java b/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostResponse.java deleted file mode 100644 index df198b0..0000000 --- a/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostResponse.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.hjjang.backend.domain.post.dto; - -import com.hjjang.backend.domain.post.domain.entity.Post; -import lombok.Builder; -import lombok.Getter; -import lombok.Setter; - -@Builder -@Getter -@Setter -public class PostResponse { - - private Long id; - - private Long user_id; - -// private Long image_id; - - private String title; - - private String content; - - private Integer item_price; - - private Integer views; - - private Integer interest_number; - - private Integer chat_number; - - private String is_sale_completion; - - private boolean removed; - - public static PostResponse of(Post post) { - return PostResponse.builder() - .id(post.getId()) - .user_id(post.getUser().getId()) -// .image_id(post.getImage().getId()) - .title(post.getTitle()) - .content(post.getContent()) - .item_price(post.getItemPrice()) - .views(post.getViews()) - .interest_number(post.getInterestNumber()) - .chat_number(post.getChatNumber()) - .is_sale_completion(post.getIsSaleCompletion()) - .removed(post.isRemoved()) - .build(); - } -} diff --git a/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostResponseDto.java b/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostResponseDto.java new file mode 100644 index 0000000..992d8c8 --- /dev/null +++ b/backend/src/main/java/com/hjjang/backend/domain/post/dto/PostResponseDto.java @@ -0,0 +1,34 @@ +package com.hjjang.backend.domain.post.dto; + +import com.hjjang.backend.domain.post.domain.entity.Post; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Builder +@Getter +@Setter +public class PostResponseDto { + + private Long id; + + private Long user_id; + + private String title; + + private String content; + + private Integer item_price; + + private Integer views; + + private Integer interest_number; + + private Integer chat_number; + + private String is_sale_completion; + + private boolean removed; + + private String time; +} diff --git a/backend/src/main/java/com/hjjang/backend/domain/post/service/PostServiceImpl.java b/backend/src/main/java/com/hjjang/backend/domain/post/service/PostServiceImpl.java index 1ffe926..caa6911 100644 --- a/backend/src/main/java/com/hjjang/backend/domain/post/service/PostServiceImpl.java +++ b/backend/src/main/java/com/hjjang/backend/domain/post/service/PostServiceImpl.java @@ -2,7 +2,11 @@ import com.hjjang.backend.domain.post.domain.entity.Post; import com.hjjang.backend.domain.post.domain.repository.PostRepository; +import com.hjjang.backend.domain.post.dto.PostRequestDto; import com.hjjang.backend.domain.post.exception.PostNotFoundException; +import com.hjjang.backend.domain.user.entity.User; +import com.hjjang.backend.domain.user.exception.UserNotMatchException; +import com.hjjang.backend.global.response.code.ErrorCode; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -14,7 +18,7 @@ public class PostServiceImpl implements PostService { private final PostRepository postRepository; - public Post save(Post post){ + public Post save(Post post) { return postRepository.save(post); } @@ -26,6 +30,12 @@ public Post findOneById(Long id) { return postRepository.findById(id).orElseThrow(PostNotFoundException::new); } + public Post updateOneById(Long id, PostRequestDto postRequestDto, User user) { + Post foundPost = findOneById(id); + if (user == foundPost.getUser()) return save(foundPost.update(postRequestDto)); + else throw new UserNotMatchException("사용자 정보가 일치하지 않습니다.", ErrorCode.NO_AUTHORITY); + } + public void deleteOneById(Long id) { findOneById(id).removePost(); } diff --git a/backend/src/main/java/com/hjjang/backend/domain/user/entity/User.java b/backend/src/main/java/com/hjjang/backend/domain/user/entity/User.java index 9b2af8d..8662ca3 100644 --- a/backend/src/main/java/com/hjjang/backend/domain/user/entity/User.java +++ b/backend/src/main/java/com/hjjang/backend/domain/user/entity/User.java @@ -4,6 +4,7 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.CreationTimestamp; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -42,7 +43,7 @@ public class User { @Column(name = "image_url", nullable = true, length = 50) private String imageUrl; - @CreatedDate + @CreationTimestamp @Column(name = "created_at", nullable = false) private LocalDateTime createdAt; diff --git a/backend/src/main/java/com/hjjang/backend/domain/user/exception/UserNotMatchException.java b/backend/src/main/java/com/hjjang/backend/domain/user/exception/UserNotMatchException.java new file mode 100644 index 0000000..1aac12b --- /dev/null +++ b/backend/src/main/java/com/hjjang/backend/domain/user/exception/UserNotMatchException.java @@ -0,0 +1,21 @@ +package com.hjjang.backend.domain.user.exception; + +import com.hjjang.backend.global.execption.BusinessException; +import com.hjjang.backend.global.response.code.ErrorCode; +import com.hjjang.backend.global.response.response.ErrorResponse; + +import java.util.List; + +public class UserNotMatchException extends BusinessException { + public UserNotMatchException(String message, ErrorCode errorCode) { + super(message, errorCode); + } + + public UserNotMatchException(ErrorCode errorCode) { + super(errorCode); + } + + public UserNotMatchException(ErrorCode errorCode, List errors) { + super(errorCode, errors); + } +} diff --git a/backend/src/test/java/com/hjjang/backend/domain/post/service/PostServiceImplTest.java b/backend/src/test/java/com/hjjang/backend/domain/post/service/PostServiceImplTest.java new file mode 100644 index 0000000..83122e5 --- /dev/null +++ b/backend/src/test/java/com/hjjang/backend/domain/post/service/PostServiceImplTest.java @@ -0,0 +1,4 @@ +import static org.junit.jupiter.api.Assertions.*; +class PostServiceImplTest { + +} \ No newline at end of file diff --git a/backend/src/test/resources/application.yml b/backend/src/test/resources/application.yml new file mode 100644 index 0000000..884acd5 --- /dev/null +++ b/backend/src/test/resources/application.yml @@ -0,0 +1,16 @@ +spring: + datasource: + url: jdbc:h2:mem:test_db;MODE=MySQL;DB_CLOSE_DELAY=-1 + driverClassName: org.h2.Driver + username: sa + password: + h2: + console: + enabled: true + jpa: + database-platform: org.hibernate.dialect.H2Dialect + hibernate.ddl-auto: create-drop + properties: + hibernate: + format_sql: true + generate-ddl: true \ No newline at end of file From 8da7c94f8f9904e9ee59ff1e3837e7d09ed21a99 Mon Sep 17 00:00:00 2001 From: 0BVer Date: Mon, 9 May 2022 23:01:13 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat=20:=20Post=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/controller/PostControllerTest.java | 33 ++++ .../domain/post/domain/entity/PostTest.java | 78 ++++++++ .../domain/repository/PostRepositoryTest.java | 150 +++++++++++++++ .../domain/post/dto/PostMapperTest.java | 102 ++++++++++ .../post/service/PostServiceImplTest.java | 178 +++++++++++++++++- 5 files changed, 540 insertions(+), 1 deletion(-) create mode 100644 backend/src/test/java/com/hjjang/backend/domain/post/controller/PostControllerTest.java create mode 100644 backend/src/test/java/com/hjjang/backend/domain/post/domain/entity/PostTest.java create mode 100644 backend/src/test/java/com/hjjang/backend/domain/post/domain/repository/PostRepositoryTest.java create mode 100644 backend/src/test/java/com/hjjang/backend/domain/post/dto/PostMapperTest.java diff --git a/backend/src/test/java/com/hjjang/backend/domain/post/controller/PostControllerTest.java b/backend/src/test/java/com/hjjang/backend/domain/post/controller/PostControllerTest.java new file mode 100644 index 0000000..6f6b69d --- /dev/null +++ b/backend/src/test/java/com/hjjang/backend/domain/post/controller/PostControllerTest.java @@ -0,0 +1,33 @@ +package com.hjjang.backend.domain.post.controller; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class PostControllerTest { + + @BeforeEach + void setUp() { + } + + @Test + void createItem() { + } + + @Test + void findAllItem() { + } + + @Test + void findOneItem() { + } + + @Test + void putOneItem() { + } + + @Test + void deleteOneItem() { + } +} \ No newline at end of file diff --git a/backend/src/test/java/com/hjjang/backend/domain/post/domain/entity/PostTest.java b/backend/src/test/java/com/hjjang/backend/domain/post/domain/entity/PostTest.java new file mode 100644 index 0000000..bdcbd7e --- /dev/null +++ b/backend/src/test/java/com/hjjang/backend/domain/post/domain/entity/PostTest.java @@ -0,0 +1,78 @@ +package com.hjjang.backend.domain.post.domain.entity; + +import com.hjjang.backend.domain.post.dto.PostRequestDto; +import com.hjjang.backend.domain.user.entity.Agreement; +import com.hjjang.backend.domain.user.entity.RoleType; +import com.hjjang.backend.domain.user.entity.User; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class PostTest { + + private Post post; + + private final String givenTitle = "test title"; + private final String givenContent = "test content"; + private final int givenItemPrice = 10000; + + @BeforeEach + void setUp() { + User givenUser = User.builder() + .providerId("test Id") + .email("user@email.ac.kr") + .imageUrl("test path") + .isPushAgree(Agreement.AGREE) + .mannerTemperature(36L) + .nickName("test NN") + .role(RoleType.USER) + .univId(1L) + .build(); + + post = Post.builder() + .user(givenUser) + .title(givenTitle) + .content(givenContent) + .itemPrice(givenItemPrice) + .build(); + } + + @Test + @DisplayName("Post 삭제 처리 테스트") + void removePostTest() { + // given + + // when + post.removePost(); + // then + assertTrue(post.isRemoved()); + } + + @Test + @DisplayName("Post 갱신 테스트") + void updateTest() { + // given + PostRequestDto givenPostRequestDto = PostRequestDto.builder() + .title(givenTitle) + .content(givenContent) + .price(givenItemPrice) + .build(); + + Post expectPost = Post.builder() + .title(givenTitle) + .content(givenContent) + .itemPrice(givenItemPrice) + .build(); + + // when + Post actualPost = post.update(givenPostRequestDto); + // then + assertAll( + () -> assertEquals(expectPost.getTitle(), actualPost.getTitle()), + () -> assertEquals(expectPost.getContent(), actualPost.getContent()), + () -> assertEquals(expectPost.getItemPrice(), actualPost.getItemPrice()) + ); + } +} \ No newline at end of file diff --git a/backend/src/test/java/com/hjjang/backend/domain/post/domain/repository/PostRepositoryTest.java b/backend/src/test/java/com/hjjang/backend/domain/post/domain/repository/PostRepositoryTest.java new file mode 100644 index 0000000..926d931 --- /dev/null +++ b/backend/src/test/java/com/hjjang/backend/domain/post/domain/repository/PostRepositoryTest.java @@ -0,0 +1,150 @@ +package com.hjjang.backend.domain.post.domain.repository; + +import com.hjjang.backend.domain.post.domain.entity.Post; +import com.hjjang.backend.domain.user.entity.Agreement; +import com.hjjang.backend.domain.user.entity.RoleType; +import com.hjjang.backend.domain.user.entity.User; +import com.hjjang.backend.domain.user.repository.UserRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.dao.DataIntegrityViolationException; + +import java.util.List; +import java.util.Optional; + +import static com.hjjang.backend.domain.post.domain.entity.PostDefaultValue.*; +import static org.junit.jupiter.api.Assertions.*; + +@DataJpaTest +@DisplayName("Post Repository 테스트") +class PostRepositoryTest { + + @Autowired + private PostRepository postRepository; + + @Autowired + private UserRepository userRepository; + + private Post expectPost1; + + private Post expectPost2; + + private Post givenPost1; + private Post givenPost2; + + private final String givenTitle = "test title"; + private final String givenContent = "test content"; + private final int givenItemPrice = 10000; + + @BeforeEach + void setUp() { + + User givenUser = User.builder() + .providerId("test Id") + .email("user@email.ac.kr") + .imageUrl("test path") + .isPushAgree(Agreement.AGREE) + .mannerTemperature(36L) + .nickName("test NN") + .role(RoleType.USER) + .univId(1L) + .build(); + + User actualUser = userRepository.save(givenUser); + + givenPost1 = Post.builder() + .user(actualUser) + .title(givenTitle) + .content(givenContent) + .itemPrice(givenItemPrice) + .build(); + + givenPost2 = Post.builder() + .user(actualUser) + .title(givenTitle) + .content(givenContent) + .itemPrice(givenItemPrice) + .build(); + + expectPost1 = postRepository.save(givenPost1); + expectPost2 = postRepository.save(givenPost2); + } + + @Test + @DisplayName("같은 정보의 Post가 저장되는지 테스트") + void saveSameTest() { + // given + + // when + Post actualPost = postRepository.save(givenPost2); + // then + assertAll( + () -> assertEquals(givenPost2.getUser(), actualPost.getUser()), + () -> assertEquals(givenPost2.getTitle(), actualPost.getTitle()), + () -> assertEquals(givenPost2.getContent(), actualPost.getContent()) + ); + } + + @Test + @DisplayName("빈 Post를 저장시킬 때 검증 절차에의해 에러가 발생하는지 테스트") + void saveEmptyPostTest() { + // given + Post emptyPost = Post.builder().build(); + // when + + // then + assertThrowsExactly(DataIntegrityViolationException.class, () -> postRepository.save(emptyPost)); + } + + @Test + @DisplayName("Post의 기본 값이 잘 설정되는지 테스트") + void saveDefaultValueTest() { + // given + + // when + Post actualPost = postRepository.save(givenPost1); + // then + assertAll( + () -> assertEquals(DEFAULT_VIEWS, actualPost.getViews()), + () -> assertEquals(DEFAULT_INTEREST_NUMBER, actualPost.getInterestNumber()), + () -> assertEquals(DEFAULT_CHAT_NUMBER, actualPost.getChatNumber()), + () -> assertEquals(DEFAULT_IS_SALE_COMPLETION, actualPost.getIsSaleCompletion()), + () -> assertEquals(DEFAULT_REMOVED, actualPost.isRemoved()) + ); + } + + @Test + @DisplayName("") + void findAllTest() { + // given + List expectPostList = List.of(expectPost1, expectPost2); + // when + List actualPostList = postRepository.findAll(); + // then + assertIterableEquals(expectPostList, actualPostList); + } + + @Test + @DisplayName("존재하는 ID로 죄회할 때 제대로 가져오는지 테스트") + void findByActualIdTest() { + // given + + // when + Post actualPost = postRepository.getById(expectPost1.getId()); + // then + assertEquals(expectPost1, actualPost); + } + + @Test + @DisplayName("존재하지 않는 ID로 조회할 때 Optional.empty()로 처리 되는지 테스트") + void findByNotRealIdTest() { + // given + long givenId = 9999999L; + // when + // then + assertEquals(Optional.empty(), postRepository.findById(givenId)); + } +} \ No newline at end of file diff --git a/backend/src/test/java/com/hjjang/backend/domain/post/dto/PostMapperTest.java b/backend/src/test/java/com/hjjang/backend/domain/post/dto/PostMapperTest.java new file mode 100644 index 0000000..883b3e2 --- /dev/null +++ b/backend/src/test/java/com/hjjang/backend/domain/post/dto/PostMapperTest.java @@ -0,0 +1,102 @@ +package com.hjjang.backend.domain.post.dto; + +import com.hjjang.backend.domain.post.domain.entity.Post; +import com.hjjang.backend.domain.user.entity.Agreement; +import com.hjjang.backend.domain.user.entity.RoleType; +import com.hjjang.backend.domain.user.entity.User; +import org.assertj.core.api.Assertions; +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.mockito.InjectMocks; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.time.LocalDateTime; + +import static com.hjjang.backend.domain.post.domain.entity.PostDefaultValue.*; +import static org.junit.jupiter.api.Assertions.*; + +@ExtendWith(SpringExtension.class) +class PostMapperTest { + + @InjectMocks + private PostMapper postMapper; + + private Post expectPost; + + private User givenUser; + + private final String givenTitle = "test title"; + private final String givenContent = "test content"; + private final int givenItemPrice = 10000; + + @BeforeEach + void setUp() { + givenUser = User.builder() + .providerId("test Id") + .email("user@email.ac.kr") + .imageUrl("test path") + .isPushAgree(Agreement.AGREE) + .mannerTemperature(36L) + .nickName("test NN") + .role(RoleType.USER) + .univId(1L) + .build(); + + expectPost = Post.builder() + .user(givenUser) + .title(givenTitle) + .content(givenContent) + .itemPrice(givenItemPrice) + .build(); + + } + + @Test + @DisplayName("PostRequestDto -> Post 변환 테스트") + void toEntityTest() { + // given + PostRequestDto givenPostRequestDto = PostRequestDto.builder() + .title(givenTitle) + .content(givenContent) + .price(givenItemPrice) + .build(); + // when + Post actualPost = postMapper.toEntity(givenPostRequestDto, givenUser); + // then + assertAll( + () -> assertEquals(expectPost.getUser(), actualPost.getUser()), + () -> assertEquals(expectPost.getTitle(), actualPost.getTitle()), + () -> assertEquals(expectPost.getContent(), actualPost.getContent()), + () -> assertEquals(expectPost.getItemPrice(), actualPost.getItemPrice()) + ); + } + + @Test + @DisplayName("Post -> PostResponseDto 변환 테스트") + void fromEntityTest() { + // given + Post givenPost = new Post(1L, givenUser, givenTitle, givenContent, givenItemPrice, + DEFAULT_VIEWS, DEFAULT_INTEREST_NUMBER, DEFAULT_CHAT_NUMBER, + DEFAULT_IS_SALE_COMPLETION, DEFAULT_REMOVED, LocalDateTime.now()); + + PostResponseDto expectPostResponseDto = PostResponseDto.builder() + .id(givenPost.getId()) + .user_id(givenPost.getUser().getId()) + .title(givenPost.getTitle()) + .content(givenPost.getContent()) + .item_price(givenPost.getItemPrice()) + .views(givenPost.getViews()) + .interest_number(givenPost.getInterestNumber()) + .chat_number(givenPost.getChatNumber()) + .is_sale_completion(givenPost.getIsSaleCompletion().getState()) + .removed(givenPost.isRemoved()) + .time(givenPost.getTime().toString()) + .build(); + // when + PostResponseDto actualPostResponseDto = postMapper.fromEntity(givenPost); + // then + Assertions.assertThat(actualPostResponseDto).isEqualToComparingFieldByField(expectPostResponseDto); + } +} \ No newline at end of file diff --git a/backend/src/test/java/com/hjjang/backend/domain/post/service/PostServiceImplTest.java b/backend/src/test/java/com/hjjang/backend/domain/post/service/PostServiceImplTest.java index 83122e5..d9d646c 100644 --- a/backend/src/test/java/com/hjjang/backend/domain/post/service/PostServiceImplTest.java +++ b/backend/src/test/java/com/hjjang/backend/domain/post/service/PostServiceImplTest.java @@ -1,4 +1,180 @@ +package com.hjjang.backend.domain.post.service; + +import com.hjjang.backend.domain.post.domain.entity.Post; +import com.hjjang.backend.domain.post.domain.repository.PostRepository; +import com.hjjang.backend.domain.post.dto.PostRequestDto; +import com.hjjang.backend.domain.post.exception.PostNotFoundException; +import com.hjjang.backend.domain.user.entity.Agreement; +import com.hjjang.backend.domain.user.entity.RoleType; +import com.hjjang.backend.domain.user.entity.User; +import com.hjjang.backend.domain.user.exception.UserNotMatchException; +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.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith(SpringExtension.class) +@DisplayName("Post 서비스 테스트") class PostServiceImplTest { - + + @InjectMocks + private PostServiceImpl postService; + + @Mock + private PostRepository postRepository; + + private Post expectPost; + + private User givenUser; + + private List expectPostList = new ArrayList<>(); + + private final long givenInvalidId = 0L; + private final long givenValidId = 1L; + + @BeforeEach + void setUp() { + givenUser = User.builder() + .providerId("test Id") + .email("user@email.ac.kr") + .imageUrl("test path") + .isPushAgree(Agreement.AGREE) + .mannerTemperature(36L) + .nickName("test NN") + .role(RoleType.USER) + .univId(1L) + .build(); + + String givenTitle = "test title"; + String givenContent = "test content"; + int givenItemPrice = 10000; + + expectPost = Post.builder() + .user(givenUser) + .title(givenTitle) + .content(givenContent) + .itemPrice(givenItemPrice) + .build(); + + expectPostList = List.of(expectPost); + + when(postRepository.save(any())).thenReturn(expectPost); + when(postRepository.findAll()).thenReturn(expectPostList); + when(postRepository.findById(givenInvalidId)).thenReturn(Optional.empty()); + when(postRepository.findById(givenValidId)).thenReturn(Optional.ofNullable(expectPost)); + } + + @Test + @DisplayName("Post 저장 테스트") + void saveTest() { + // given + + // when + Post actualPost = postService.save(expectPost); + // then + assertEquals(expectPost, actualPost); + } + + @Test + @DisplayName("Post 리스트를 잘 불러오는지 테스트") + void findAllTest() { + // given + + // when + List actualPostList = postService.findAll(); + // then + assertIterableEquals(expectPostList, actualPostList); + } + + @Test + @DisplayName("존재하는 Id로 검색을 요청할 때 제대로 불러오는지 테스트") + void findOneByValidIdTest() { + // given + + // when + Post actualPost = postService.findOneById(givenValidId); + // then + assertEquals(expectPost, actualPost); + } + + @Test + @DisplayName("존재하지 않는 Id로 검색을 요청할 때 제대로 예외를 발생 시키는지 테스트") + void findOneByInvalidIdTest() { + // given + + // when + + // then + assertThrowsExactly(PostNotFoundException.class, () -> postService.findOneById(givenInvalidId)); + } + + @Test + @DisplayName("올바른 User 정보를 가질 때, Post 변경이 잘 반영되는지 테스트") + void updateOneByIdWithValidUserTest() { + // given + String changedTitle = "changed title"; + String changedContent = "changed content"; + int changedPrice = 999999; + + PostRequestDto givenPostRequestDto = PostRequestDto.builder() + .title(changedTitle) + .content(changedContent) + .price(changedPrice) + .build(); + + Post expectPost = Post.builder() + .user(givenUser) + .title(changedTitle) + .content(changedTitle) + .itemPrice(changedPrice) + .build(); + + when(postService.save(any())).thenReturn(expectPost); + // when + Post actualPost = postService.updateOneById(givenValidId, givenPostRequestDto, givenUser); + // then + assertEquals(expectPost, actualPost); + } + + @Test + @DisplayName("올바르지 않은 User 정보를 가질 때, 예외를 처리하는지 테스트") + void updateOneByIdWithInvalidUserTest() { + // given + String changedTitle = "changed title"; + String changedContent = "changed content"; + int changedPrice = 999999; + + PostRequestDto givenPostRequestDto = PostRequestDto.builder() + .title(changedTitle) + .content(changedContent) + .price(changedPrice) + .build(); + + User invalidUser = User.builder().build(); + // when + + // then + assertThrowsExactly(UserNotMatchException.class, () -> postService.updateOneById(givenValidId, givenPostRequestDto, invalidUser)); + } + + @Test + @DisplayName("삭제 처리에서 예외가 발생하지 않는지 테스트") + void deleteOneByIdTest() { + // given + + // when + + // then + assertDoesNotThrow(() -> postService.deleteOneById(givenValidId)); + } } \ No newline at end of file From 8d32db4a1ff7147097cee9fa0e53b20b0500f2a0 Mon Sep 17 00:00:00 2001 From: 0BVer Date: Wed, 11 May 2022 00:46:47 +0900 Subject: [PATCH 6/6] =?UTF-8?q?feat=20:=20post=20=EC=BB=A8=ED=8A=B8?= =?UTF-8?q?=EB=A1=A4=EB=9F=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20(=EB=AF=B8?= =?UTF-8?q?=EC=99=84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/controller/PostControllerTest.java | 178 +++++++++++++++++- 1 file changed, 175 insertions(+), 3 deletions(-) diff --git a/backend/src/test/java/com/hjjang/backend/domain/post/controller/PostControllerTest.java b/backend/src/test/java/com/hjjang/backend/domain/post/controller/PostControllerTest.java index 6f6b69d..5ed3ef6 100644 --- a/backend/src/test/java/com/hjjang/backend/domain/post/controller/PostControllerTest.java +++ b/backend/src/test/java/com/hjjang/backend/domain/post/controller/PostControllerTest.java @@ -1,18 +1,190 @@ package com.hjjang.backend.domain.post.controller; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.hjjang.backend.domain.post.domain.entity.Post; +import com.hjjang.backend.domain.post.domain.entity.PostDefaultValue; +import com.hjjang.backend.domain.post.dto.PostMapper; +import com.hjjang.backend.domain.post.dto.PostRequestDto; +import com.hjjang.backend.domain.post.dto.PostResponseDto; +import com.hjjang.backend.domain.post.service.PostServiceImpl; +import com.hjjang.backend.domain.user.entity.Agreement; +import com.hjjang.backend.domain.user.entity.RoleType; +import com.hjjang.backend.domain.user.entity.User; +import com.hjjang.backend.domain.user.repository.UserRefreshTokenRepository; +import com.hjjang.backend.global.config.properties.AuthProperties; +import com.hjjang.backend.global.config.security.handler.TokenAccessDeniedHandler; +import com.hjjang.backend.global.config.security.service.CustomOAuth2UserService; +import com.hjjang.backend.global.config.security.token.AuthTokenProvider; +import com.hjjang.backend.global.util.UserUtil; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +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.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.RequestBuilder; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.filter.CharacterEncodingFilter; -import static org.junit.jupiter.api.Assertions.*; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import static com.hjjang.backend.domain.post.domain.entity.PostDefaultValue.*; +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@ExtendWith(SpringExtension.class) +@WebMvcTest(controllers = PostController.class) +//@ExtendWith(RestDocumentationExtension.class) +//@AutoConfigureRestDocs class PostControllerTest { + //TODO security 관련 종속성을 어떻게 해결해야 할지 모르겠음 아마도 MockBean 으로 만들고 모두 when then 을 설정하면 되지 않을까 싶은데 너무 비효율 적 + @MockBean private PostServiceImpl postService; + @MockBean private PostMapper postMapper; + @MockBean private UserUtil userUtil; +// @MockBean private AuthProperties authProperties; +// @MockBean private AuthTokenProvider authTokenProvider; +// @MockBean private CustomOAuth2UserService customOAuth2UserService; +// @MockBean private TokenAccessDeniedHandler tokenAccessDeniedHandler; +// @MockBean private UserRefreshTokenRepository userRefreshTokenRepository; + + private MockMvc mockMvc; + + private ObjectMapper objectMapper; + + private final long givenId = 1L; + + private final String givenTitle = "test title"; + private final String givenContent = "test content"; + private final int givenItemPrice = 10000; + + private final String changedTitle = "changed Title"; + private final String changedContent = "changed Content"; + private final int changedItemPrice = 999999; + + private final String providerId = "provider Id"; + private final String nickName = "NN"; + private final String email = "user@email.ac.kr"; + private final long mannerTemperature = 36L; + private final String imagePath = "image path"; + private final Agreement pushAgree = Agreement.AGREE; + private final long univId = 1L; + private final RoleType role = RoleType.USER; + + private final Map givenPostRequestJson = new HashMap<>(); + + private PostResponseDto expectPostResponseDto; + + private final Map expectApiResponseJson = new HashMap<>(); + @BeforeEach - void setUp() { + void setUp(WebApplicationContext context) { + objectMapper = new ObjectMapper(); + + mockMvc = MockMvcBuilders + .webAppContextSetup(context) + .addFilter(new CharacterEncodingFilter(StandardCharsets.UTF_8.name(), true)) + .build(); + + givenPostRequestJson.put("title", givenTitle); + givenPostRequestJson.put("content", givenContent); + givenPostRequestJson.put("price", String.valueOf(givenItemPrice)); + + User givenUser = User.builder() + .providerId(providerId) + .email(email) + .imageUrl(imagePath) + .isPushAgree(pushAgree) + .mannerTemperature(mannerTemperature) + .nickName(nickName) + .role(role) + .univId(univId) + .build(); + + Post expectRawPost = Post.builder() + .user(givenUser) + .title(givenTitle) + .content(givenContent) + .itemPrice(givenItemPrice) + .build(); + + User expectSavedUser = new User(givenId, providerId, nickName, email, + mannerTemperature, imagePath, LocalDateTime.now(), pushAgree, univId, role); + + Post expectSavedPost = new Post(givenId, givenUser, givenTitle, givenContent, givenItemPrice, + DEFAULT_VIEWS, DEFAULT_INTEREST_NUMBER, DEFAULT_CHAT_NUMBER, + DEFAULT_IS_SALE_COMPLETION, DEFAULT_REMOVED, LocalDateTime.now()); + + Post expectUpdatedPost = new Post(givenId, givenUser, changedTitle, changedContent, + changedItemPrice, DEFAULT_VIEWS, DEFAULT_INTEREST_NUMBER, DEFAULT_CHAT_NUMBER, + DEFAULT_IS_SALE_COMPLETION, DEFAULT_REMOVED, LocalDateTime.now()); + + expectPostResponseDto = PostResponseDto.builder() + .id(expectSavedPost.getId()) + .user_id(expectSavedPost.getUser().getId()) + .title(expectSavedPost.getTitle()) + .content(expectSavedPost.getContent()) + .item_price(expectSavedPost.getItemPrice()) + .views(expectSavedPost.getViews()) + .interest_number(expectSavedPost.getInterestNumber()) + .chat_number(expectSavedPost.getChatNumber()) + .is_sale_completion(expectSavedPost.getIsSaleCompletion().getState()) + .removed(expectSavedPost.isRemoved()) + .time(expectSavedPost.getTime().toString()) + .build(); + + expectApiResponseJson.put("id", String.valueOf(givenId)); + expectApiResponseJson.put("user_id", String.valueOf(givenId)); + expectApiResponseJson.put("title", givenTitle); + expectApiResponseJson.put("content", givenContent); + expectApiResponseJson.put("item_price", String.valueOf(givenItemPrice)); + expectApiResponseJson.put("views", String.valueOf(DEFAULT_VIEWS)); + expectApiResponseJson.put("interest_number", String.valueOf(DEFAULT_INTEREST_NUMBER)); + expectApiResponseJson.put("chat_number", String.valueOf(DEFAULT_CHAT_NUMBER)); + expectApiResponseJson.put("removed", String.valueOf(DEFAULT_REMOVED)); + expectApiResponseJson.put("time", String.valueOf(LocalDateTime.now())); + + List expectPostList = List.of(expectSavedPost); + + when(postMapper.fromEntity(any())).thenReturn(expectPostResponseDto); + when(postMapper.toEntity(any(), any())).thenReturn(expectRawPost); + when(postService.save(expectRawPost)).thenReturn(expectSavedPost); + when(postService.findAll()).thenReturn(expectPostList); + when(postService.findOneById(anyLong())).thenReturn(expectSavedPost); + when(postService.updateOneById(anyLong(), any(PostRequestDto.class), any(User.class))) + .thenReturn(expectUpdatedPost); + doNothing().when(postService).deleteOneById(anyLong()); + + when(userUtil.getLoginUserByToken()).thenReturn(expectSavedUser); } @Test - void createItem() { + void createItemTest() throws Exception { + //given + Map expectResponseEntityJson = new HashMap<>(); + expectResponseEntityJson.put("name", "createItem"); + expectResponseEntityJson.put("body", expectApiResponseJson); + //when + + //then + mockMvc.perform(RestDocumentationRequestBuilders.post("/api/posts") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(givenPostRequestJson))) + .andExpect(status().isCreated()) + .andExpect(content().json(objectMapper.writeValueAsString(expectResponseEntityJson))); } @Test