Skip to content

Commit

Permalink
문의 답변 생성 (#98)
Browse files Browse the repository at this point in the history
* 문의 답변 생성

* chore : ReplyCreateController 메서드 명 & 파라미터 이름 수정
  • Loading branch information
kgh2120 authored May 5, 2023
1 parent 3e1034b commit a80624f
Show file tree
Hide file tree
Showing 10 changed files with 309 additions and 35 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.liberty52.product.global.contants;

public class RoleConstants {

public static final String ADMIN = "ADMIN";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.liberty52.product.service.applicationservice;

import com.liberty52.product.service.controller.dto.ReplyCreateRequestDto;

public interface ReplyCreateService {
void createReply(String adminId, ReplyCreateRequestDto dto, String reviewId, String role);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.liberty52.product.service.applicationservice;

import static com.liberty52.product.global.contants.RoleConstants.ADMIN;

import com.liberty52.product.global.exception.external.forbidden.InvalidRoleException;
import com.liberty52.product.global.exception.external.notfound.ResourceNotFoundException;
import com.liberty52.product.service.controller.dto.ReplyCreateRequestDto;
import com.liberty52.product.service.entity.Reply;
import com.liberty52.product.service.entity.Review;
import com.liberty52.product.service.repository.ReviewRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
@RequiredArgsConstructor
public class ReplyCreateServiceImpl implements
ReplyCreateService {

private final ReviewRepository reviewRepository;

@Override
public void createReply(String reviewerId, ReplyCreateRequestDto dto, String reviewId,
String role) {
if(!ADMIN.equals(role))
throw new InvalidRoleException(role);



Review review = reviewRepository.findById(reviewId)
.orElseThrow(() -> new ResourceNotFoundException("Review", "ID", reviewId));
Reply reply = Reply.create(dto.getContent(), reviewerId);
reply.associate(review);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,4 @@

public interface ReviewCreateService {
void createReview(String reviewerId,ReviewCreateRequestDto dto, List<MultipartFile> imageFile);

void createReply(String reviewerId, ReplyCreateRequestDto dto, String reviewId);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.liberty52.product.service.applicationservice;

import static com.liberty52.product.global.contants.RoleConstants.ADMIN;

import com.liberty52.product.global.adapter.s3.S3UploaderApi;
import com.liberty52.product.global.exception.external.badrequest.BadRequestException;
import com.liberty52.product.global.exception.external.badrequest.ReviewAlreadyExistByOrderException;
import com.liberty52.product.global.exception.external.forbidden.InvalidRoleException;
import com.liberty52.product.global.exception.external.forbidden.NotYourOrderException;
import com.liberty52.product.global.exception.external.notfound.CustomProductNotFoundByIdException;
import com.liberty52.product.global.exception.external.notfound.OrderNotFoundByIdException;
Expand Down Expand Up @@ -63,17 +66,6 @@ public void createReview(String reviewerId, ReviewCreateRequestDto dto, List<Mul
}
reviewRepository.save(review);
}


@Override
public void createReply(String reviewerId, ReplyCreateRequestDto dto, String reviewId) {
Review review = reviewRepository.findById(reviewId)
.orElseThrow(() -> new ResourceNotFoundException("Review", "ID", reviewId));
Reply reply = Reply.create(dto.getContent(), reviewerId);
reply.associate(review);
}


private void addImage(List<MultipartFile> imageFiles, Review review) {
if (imageFiles.size() > Review.IMAGES_MAX_COUNT)
throw new BadRequestException(1 + " <= Size of images <= " + Review.IMAGES_MAX_COUNT);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.liberty52.product.service.controller;


import com.liberty52.product.service.applicationservice.ReplyCreateService;
import com.liberty52.product.service.controller.dto.ReplyCreateRequestDto;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class ReplyCreateController {

private final ReplyCreateService replyCreateService;

@PostMapping("/reviews/{reviewId}/replies")
@ResponseStatus(HttpStatus.CREATED)
public void createReply(@RequestHeader(HttpHeaders.AUTHORIZATION) String adminId,
@RequestHeader("X-ROLE") String role,
@Validated @RequestBody ReplyCreateRequestDto dto, @PathVariable String reviewId) {
replyCreateService.createReply(adminId,dto,reviewId, role);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,4 @@ public void reviewCreate( @RequestHeader(HttpHeaders.AUTHORIZATION) String revie
@RequestPart(value = "images",required = false) List<MultipartFile> images) {
reviewCreateService.createReview(reviewerId,dto,images);
}

@PostMapping("/reviews/{reviewId}/replies")
@ResponseStatus(HttpStatus.CREATED)
public void replyCreate(@RequestHeader(HttpHeaders.AUTHORIZATION) String reviewerId,
@Validated @RequestBody ReplyCreateRequestDto dto, @PathVariable String reviewId) {
reviewCreateService.createReply(reviewerId,dto,reviewId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.liberty52.product.service.applicationservice;

import static com.liberty52.product.global.contants.RoleConstants.ADMIN;
import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;

import com.liberty52.product.global.config.DBInitConfig.DBInitService;
import com.liberty52.product.global.exception.external.forbidden.InvalidRoleException;
import com.liberty52.product.global.exception.external.notfound.ResourceNotFoundException;
import com.liberty52.product.service.controller.dto.ReplyCreateRequestDto;
import com.liberty52.product.service.entity.Reply;
import com.liberty52.product.service.repository.ReplyRepository;
import jakarta.persistence.EntityManager;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

@Transactional
@SpringBootTest
class ReplyCreateServiceImplTest {

@Autowired
ReplyCreateService service;

final String mockAdminId = "bar";
final String mockUserRole = "USER";
final String mockReplyContent = "Hello world";
final String mockReviewId = "foo";

@Autowired
EntityManager em;

@AfterEach
void afterEach() {

}

@Test
void Create_Reply_Success() throws Exception {
//given
String reviewId = DBInitService.getReview().getId();
ReplyCreateRequestDto dto = ReplyCreateRequestDto.createForTest(mockReplyContent);
service.createReply(mockAdminId, dto, reviewId, ADMIN);
//when
Reply finded = em.createQuery(
"select r from Reply r where r.review.id = :id and r.authId = :authId", Reply.class)
.setParameter("id", reviewId)
.setParameter("authId", mockAdminId)
.getSingleResult();

//then
assertThat(finded).isNotNull();
assertThat(finded.getContent()).isEqualTo(mockReplyContent);
assertThat(finded.getAuthId()).isEqualTo(mockAdminId);


}

@Test
void CREATE_REPLY_FAIL_InvalidRoleException() throws Exception {
//given
String reviewId = mockReviewId;
ReplyCreateRequestDto dto = ReplyCreateRequestDto.createForTest(mockReplyContent);
//when
assertThatThrownBy(() -> service.createReply(mockAdminId, dto, reviewId, mockUserRole))
.isInstanceOf(InvalidRoleException.class);

}

@Test
void CREATE_REPLY_FAIL_ResourceNotFoundException() throws Exception {
//given
String reviewId = mockReviewId;
ReplyCreateRequestDto dto = ReplyCreateRequestDto.createForTest(mockReplyContent);
//when
assertThatThrownBy(() -> service.createReply(mockAdminId, dto, reviewId, ADMIN))
.isInstanceOf(ResourceNotFoundException.class);

//then

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -82,19 +82,4 @@ void createReview() {
reviewRepository.save(review);
}

@Test
@Order(2)
void createReply() {
createReview();
String content = "is very nice reply";
ReplyCreateRequestDto dto = ReplyCreateRequestDto.createForTest(content);

Review review = reviewRepository.findByOrder(order).get();
reviewCreateService.createReply(reviewerId, dto, review.getId());

Reply reply = Reply.create(content, reviewerId);
Assertions.assertEquals(content, reply.getContent());
Assertions.assertEquals(reviewerId, reply.getAuthId());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package com.liberty52.product.service.controller;

import static com.liberty52.product.global.contants.RoleConstants.ADMIN;
import static com.liberty52.product.service.utils.MockConstants.MOCK_AUTH_ID;
import static com.liberty52.product.service.utils.MockConstants.MOCK_ORDER_ID;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.liberty52.product.global.exception.external.ErrorResponse;
import com.liberty52.product.global.exception.external.RestExceptionHandler;
import com.liberty52.product.global.exception.external.badrequest.CannotAccessOrderException;
import com.liberty52.product.global.exception.external.forbidden.InvalidRoleException;
import com.liberty52.product.global.exception.external.notfound.ResourceNotFoundException;
import com.liberty52.product.service.applicationservice.ReplyCreateService;
import com.liberty52.product.service.controller.dto.ReplyCreateRequestDto;
import org.junit.jupiter.api.Test;
import org.mockito.BDDMockito;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.web.servlet.MockMvc;


@WebMvcTest(value = {ReplyCreateController.class, RestExceptionHandler.class})
class ReplyCreateControllerTest {

@InjectMocks
ReplyCreateController controller;

@MockBean
ReplyCreateService replyCreateService;
@MockBean
RestExceptionHandler exceptionHandler;

@Autowired
MockMvc mockMvc;

final String mockReviewId = "foo";
final String createReplyUrl = "/reviews/%s/replies";
final String mockAdminId = "bar";
final String mockAdminRole = ADMIN;
final String mockUserRole = "USER";
final String mockReplyContent = "Hello world";
@Test
void Craete_Reply_Success_Status_CRAETED () throws Exception{
//given
ReplyCreateRequestDto dto = ReplyCreateRequestDto.createForTest(mockReplyContent);
//when
mockMvc.perform(post(String.format(createReplyUrl,mockReviewId))
.header(HttpHeaders.AUTHORIZATION,mockAdminId)
.header("X-ROLE",mockAdminRole)
.contentType(MediaType.APPLICATION_JSON)
.content(new ObjectMapper().writeValueAsString(dto)))
//then
.andExpect(status().isCreated())
.andDo(print());
}

@Test
void CREATE_REPLY_FAIL_STATUS_FORBIDDEN_InvalidRoleException () throws Exception{
//given
InvalidRoleException exception = new InvalidRoleException(mockUserRole);
doThrow(InvalidRoleException.class)
.when(replyCreateService)
.createReply(any(),any(),any(),any());;

given(exceptionHandler.handleGlobalException(any(),any()))
.willReturn(
ResponseEntity.status(HttpStatus.FORBIDDEN)
.body(ErrorResponse.createErrorResponse(exception, String.format(createReplyUrl,mockReviewId)))
);

ReplyCreateRequestDto dto = ReplyCreateRequestDto.createForTest(mockReplyContent);
//when
mockMvc.perform(post(String.format(createReplyUrl,mockReviewId))
.header(HttpHeaders.AUTHORIZATION,mockAdminId)
.header("X-ROLE",mockUserRole)
.contentType(MediaType.APPLICATION_JSON)
.content(new ObjectMapper().writeValueAsString(dto)))
//then
.andExpect(status().is(exception.getHttpStatus().value()))
.andExpect(jsonPath("$.httpStatus").value(exception.getHttpStatus().getReasonPhrase().toUpperCase()))
.andExpect(jsonPath("$.errorCode").value(exception.getErrorCode()))
.andExpect(jsonPath("$.errorMessage").value(exception.getErrorMessage()))
.andExpect(jsonPath("$.errorName").value(exception.getErrorName()))
.andExpect(jsonPath("$.path").value(String.format(createReplyUrl,mockReviewId)))
.andDo(print());

}

@Test
void CREATE_REPLY_FAIL_STATUS_NOT_FOUND_ResourceNotFoundException () throws Exception{
//given
ResourceNotFoundException exception = new ResourceNotFoundException("Review", "ID", mockReviewId);
doThrow(ResourceNotFoundException.class)
.when(replyCreateService)
.createReply(any(),any(),any(),any());;

given(exceptionHandler.handleGlobalException(any(),any()))
.willReturn(
ResponseEntity.status(exception.getHttpStatus())
.body(ErrorResponse.createErrorResponse(exception, String.format(createReplyUrl,mockReviewId)))
);

ReplyCreateRequestDto dto = ReplyCreateRequestDto.createForTest(mockReplyContent);
//when
mockMvc.perform(post(String.format(createReplyUrl,mockReviewId))
.header(HttpHeaders.AUTHORIZATION,mockAdminId)
.header("X-ROLE",mockAdminRole)
.contentType(MediaType.APPLICATION_JSON)
.content(new ObjectMapper().writeValueAsString(dto)))
//then
.andExpect(status().is(exception.getHttpStatus().value()))
.andExpect(jsonPath("$.httpStatus").value(exception.getHttpStatus().getReasonPhrase().toUpperCase().replace(" ","_")))
.andExpect(jsonPath("$.errorCode").value(exception.getErrorCode()))
.andExpect(jsonPath("$.errorMessage").value(exception.getErrorMessage()))
.andExpect(jsonPath("$.errorName").value(exception.getErrorName()))
.andExpect(jsonPath("$.path").value(String.format(createReplyUrl,mockReviewId)))
.andDo(print());


}

}

0 comments on commit a80624f

Please sign in to comment.