appling 프로젝트
[appling] 나머지 Controller 작업 및 Test Code 추가 작성
studyingJuno
2024. 9. 8. 23:44
728x90
반응형
🔴 나머지 Controller 작업
🟠 put, get
🟢 put
@ApiController
@RequiredArgsConstructor
@Tag(name = "Product", description = "Product API Documentation")
public class ProductController {
private final ProductService productService;
...
@PutMapping("/product")
@Operation(summary = "상품 수정", description = "상품 수정 api")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "정상", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)),
@ApiResponse(responseCode = "500", description = "서버 에러", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)),
})
public ResponseEntity<ResponseData<PostProductResponse>> putProduct(@RequestBody @Validated PutProductRequest putProductRequest) {
return ResponseEntity.status(HttpStatus.OK)
.body(ResponseData.from(ResponseDataCode.SUCCESS, productService.putProduct(putProductRequest)));
}
}
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class PutProductRequest {
@JsonProperty("product_id")
@NotNull(message = "상품 번호를 입력해 주세요.")
@Schema(description = "상품 번호", example = "1")
private Long productId;
@NotNull(message = "상품명을 입력해 주세요.")
@JsonProperty("product_name")
@Schema(description = "상품명", example = "시나노 골드")
private String productName;
@NotNull(message = "상품 무게를 입력해 주세요.")
@JsonProperty("product_weight")
@Schema(description = "상품 무게", example = "10")
private int productWeight;
@NotNull(message = "상품 타입을 입력해 주세요. ex) 사과는 11과")
@JsonProperty("product_type")
@Schema(description = "상품 타입", example = "13과")
private String productType;
@NotNull(message = "상품 가격을 입력해 주세요.")
@JsonProperty("product_price")
@Schema(description = "상품 가격", example = "150000")
private int productPrice;
@NotNull(message = "상품 수량을 입력해 주세요.")
@JsonProperty("product_stock")
@Schema(description = "상품 수량", example = "0")
private int productStock;
@NotNull(message = "상품 상태를 입력해 주세요.")
@JsonProperty("product_status")
@Schema(description = "상품 상태", example = "SOLD_OUT")
private ProductStatus productStatus;
}
🟢 get
@ApiController
@RequiredArgsConstructor
@Tag(name = "Product", description = "Product API Documentation")
public class ProductController {
private final ProductService productService;
...
@GetMapping("/product")
@Operation(summary = "상품리스트", description = "상품리스트 api")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "정상", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)),
@ApiResponse(responseCode = "500", description = "서버 에러", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))
})
public ResponseEntity<ResponseData<ProductListResponse>> getProductList(
@Schema(description = "페이지 크기", defaultValue = "10", nullable = true) @RequestParam(required = false, defaultValue = "10" ) int size,
@Schema(description = "페이지 번호", defaultValue = "0", nullable = true) @RequestParam(required = false, defaultValue = "0") int page,
@Schema(description = "페이지 정렬(proudct id 기준)", defaultValue = "DESC", nullable = true) @RequestParam(required = false, defaultValue = "DESC" ) Sort sort,
@Schema(description = "검색어(아직 기능 개발 안함)", defaultValue = "", nullable = true) @RequestParam(required = false, defaultValue = "") String search) {
return ResponseEntity.status(HttpStatus.OK)
.body(ResponseData.from(ResponseDataCode.SUCCESS, productService.getProductList(GetProductListRequest.from(size, page, sort, search))));
}
}
🟠 Test Code 작성
build를 해보니 jacoco에서 coverage를 충족시키지 못해 터져버린다. controller에 test를 까먹었다. test code를 작성하자!
🟢 post
@SpringBootTest
@AutoConfigureMockMvc
class ProductControllerTest {
@Autowired
private ObjectMapper objectMapper;
@Autowired
private MockMvc mockMvc;
@Test
@DisplayName("/post/product")
void postProduct() throws Exception {
//given
PostProductRequest productRequest = PostProductRequest.builder()
.productName("등록 상품")
.productWeight(5)
.productPrice(10000)
.productStock(10)
.productType("11과")
.build();
//when
ResultActions perform = mockMvc.perform(post("/api/v1/product")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(productRequest)));
//then
perform.andExpect(status().isCreated());
}
}
🟢 put
@SpringBootTest
@AutoConfigureMockMvc
@Transactional(readOnly = true)
class ProductControllerTest {
@Autowired
private ObjectMapper objectMapper;
@Autowired
private MockMvc mockMvc;
@Autowired
private ProductRepository productRepository;
@BeforeEach
void setUp() {
productRepository.deleteAll();
}
...
@Test
@DisplayName("[PUT] /api/v1/product")
void putProduct() throws Exception {
//given
PostProductRequest productRequest = PostProductRequest.builder()
.productName("등록 상품")
.productWeight(5)
.productPrice(10000)
.productStock(10)
.productType("11과")
.build();
ProductEntity saveProduct = productRepository.save(productRequest.toProductEntity());
PutProductRequest putProductRequest = PutProductRequest.builder()
.productId(saveProduct.getProductId())
.productType("12과")
.productPrice(100000)
.productStock(10)
.productWeight(10)
.productName("수정 상품")
.productStatus(ProductStatus.ON_SALE)
.build();
//when
ResultActions perform = mockMvc.perform(put("/api/v1/product")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(putProductRequest)));
//then
perform.andExpect(status().isOk());
}
}
🟢 get
@SpringBootTest
@AutoConfigureMockMvc
@Transactional(readOnly = true)
class ProductControllerTest {
@Autowired
private ObjectMapper objectMapper;
@Autowired
private MockMvc mockMvc;
@Autowired
private ProductRepository productRepository;
@BeforeEach
void setUp() {
productRepository.deleteAll();
}
...
@Test
@DisplayName("[GET] /api/v1/product")
void getProduct() throws Exception {
//given
PostProductRequest productRequest = PostProductRequest.builder()
.productName("등록 상품")
.productWeight(5)
.productPrice(10000)
.productStock(10)
.productType("11과")
.build();
ProductEntity saveProduct1 = productRepository.save(productRequest.toProductEntity());
ProductEntity saveProduct2 = productRepository.save(productRequest.toProductEntity());
//when
ResultActions perform = mockMvc.perform(get("/api/v1/product").param("size", "10").param("page", "0").param("sort", "DESC"));
//then
perform.andExpect(status().isOk());
}
}
🟠 branch coverage
controller를 모두 작성했는데 build에서 또 터지더라 이유를 보니 ProductCustomRepository에서 커버리지가 50프로로 나왔다. 로직을 보니 중간에 조건에 따라 분기되는 곳이 있는데 한쪽 로직만 테스트를 했던 것이다.
해당 부분도 테스트 코드를 추가해주자
🟢 로직
@Repository
@RequiredArgsConstructor
public class ProductCustomRepositoryImpl implements ProductCustomRepository{
private final JPAQueryFactory querydsl;
@Override
public Page<ProductEntity> findAll(GetProductListRequest getProductListRequest) {
Pageable pageable = Pageable.ofSize(getProductListRequest.getSize()).withPage(getProductListRequest.getPage());
Sort sort = getProductListRequest.getSort();
QProductEntity product = QProductEntity.productEntity;
List<ProductEntity> fetch = querydsl.selectFrom(product)
.orderBy(sort == Sort.ASC ? product.productId.asc() : product.productId.desc())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
Long total = querydsl.selectFrom(product).fetch().stream().count();
return new PageImpl<>(fetch, pageable, total);
}
}
여기서 orderBy()를 결정할때 분기처리 되어 있는데 해당 부분의 DESC만 테스트를 하고 있었다.
🟢 Test
@SpringBootTest
@Transactional(readOnly = true)
class ProductCustomRepositoryImplTest {
@Autowired
private ProductCustomRepository productCustomRepository;
@Autowired
private ProductRepository productRepository;
@BeforeEach
void setUp() {
productRepository.deleteAll();
}
@Test
@DisplayName("findAll asc 성공")
void findAllASC() {
//given
PostProductRequest productRequest = PostProductRequest.builder()
.productName("등록 상품")
.productWeight(5)
.productPrice(10000)
.productStock(10)
.productType("11과")
.build();
ProductEntity saveProduct1 = productRepository.save(productRequest.toProductEntity());
ProductEntity saveProduct2 = productRepository.save(productRequest.toProductEntity());
//when
Page<ProductEntity> productPage = productCustomRepository.findAll(GetProductListRequest.from(10, 0, Sort.ASC, ""));
//then
Assertions.assertThat(productPage.getContent().get(0).getProductId()).isEqualTo(saveProduct1.getProductId());
}
@Test
@DisplayName("findAll desc 성공")
void findAllDESC() {
//given
PostProductRequest productRequest = PostProductRequest.builder()
.productName("등록 상품")
.productWeight(5)
.productPrice(10000)
.productStock(10)
.productType("11과")
.build();
ProductEntity saveProduct1 = productRepository.save(productRequest.toProductEntity());
ProductEntity saveProduct2 = productRepository.save(productRequest.toProductEntity());
//when
Page<ProductEntity> productPage = productCustomRepository.findAll(GetProductListRequest.from(10, 0, Sort.DESC, ""));
//then
Assertions.assertThat(productPage.getContent().get(0).getProductId()).isEqualTo(saveProduct2.getProductId());
}
}
다른 곳에서 DESC를 테스트하고 있긴 하지만 해당 테스트 코드가 수정되면 결국 여기서 또 터지기 때문에 2개의 케이스로 테스트를 진행했다.
이제 정상적으로 Build가 되었다!
728x90
반응형