appling 프로젝트
[appling] Product 수정
studyingJuno
2024. 9. 4. 12:46
728x90
반응형
🔴 Product 상품 수정
🟠 도메인 정리
🟢 Request
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class PutProductRequest {
@JsonProperty("product_id")
@NotNull(message = "상품 번호를 입력해 주세요.")
private Long productId;
@NotNull(message = "상품명을 입력해 주세요.")
@JsonProperty("product_name")
private String productName;
@NotNull(message = "상품 무게를 입력해 주세요.")
@JsonProperty("product_weight")
private int productWeight;
@NotNull(message = "상품 타입을 입력해 주세요. ex) 사과는 11과")
@JsonProperty("product_type")
private String productType;
@NotNull(message = "상품 가격을 입력해 주세요.")
@JsonProperty("product_price")
private int productPrice;
@NotNull(message = "상품 수량을 입력해 주세요.")
@JsonProperty("product_stock")
private int productStock;
@NotNull(message = "상품 상태를 입력해 주세요.")
@JsonProperty("product_status")
private ProductStatus productStatus;
}
수정용 PutProductRequest를 정의했다.
🟢 Response
@Builder
public record PutProductResponse(
Long productId,
String productName,
int productWeight,
String productType,
ProductStatus productStatus,
int productPrice,
int productStock
) {
public static PutProductResponse from(ProductEntity updateProductEntity) {
return PutProductResponse.builder()
.productId(updateProductEntity.getProductId())
.productName(updateProductEntity.getProductName())
.productWeight(updateProductEntity.getProductWeight())
.productType(updateProductEntity.getProductType())
.productStatus(updateProductEntity.getProductStatus())
.productPrice(updateProductEntity.getProductPrice())
.productStock(updateProductEntity.getProductStock())
.build();
}
}
수정용 response인 PutProductResponse도 정의했다.
🟠 서비스 정리
🟢 Service
public interface ProductService {
...
PutProductResponse putProduct(PutProductRequest putProductRequest);
}
interface 에 추가로 작성하고
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ProductServiceImpl implements ProductService {
private final ProductRepository productRepository;
...
@Transactional
@Override
public PutProductResponse putProduct(PutProductRequest putProductRequest) {
ProductEntity productEntity = productRepository.findById(putProductRequest.getProductId())
.orElseThrow(() -> new IllegalArgumentException("유효하지 않은 상품입니다."));
productEntity.update(putProductRequest);
ProductEntity updateProductEntity = productRepository.save(productEntity);
return PutProductResponse.from(updateProductEntity);
}
}
Service에도 추가로 로직을 작성해준다. 여기서 Entity에서 update를 해야되는 상황이 생기는데 해당 부분은 Entity에 정의해주었다.
🟢 Entity
@Entity
@Table(name = "product")
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Builder
@Getter
public class ProductEntity extends CommonEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long productId;
private String productName;
private int productWeight;
private String productType;
private ProductStatus productStatus;
private int productPrice;
private int productStock;
public void update(PutProductRequest putProductRequest) {
this.productName = putProductRequest.getProductName();
this.productWeight = putProductRequest.getProductWeight();
this.productType = putProductRequest.getProductType();
this.productPrice = putProductRequest.getProductPrice();
this.productStock = putProductRequest.getProductStock();
this.productStatus = putProductRequest.getProductStatus();
}
}
Entity에 update 메서드를 추가해주었다.
🟢 Test
@SpringBootTest
class ProductServiceImplTest {
@Autowired
private ProductServiceImpl productService;
@Autowired
private ProductRepository productRepository;
@Test
@DisplayName("상품 등록에 성공한다.")
void createProduct() {
//given
PostProductRequest productRequest = PostProductRequest.builder()
.productName("아리수")
.productWeight(5)
.productType("11과")
.productPrice(100_000)
.productStock(100)
.build();
//when
PostProductResponse product = productService.createProduct(productRequest);
//then
Assertions.assertThat(product.productId()).isNotNull();
}
@Test
@DisplayName("상풍 번호가 유효하지 않으면 수정에 실패한다.")
void putProductFail() {
//given
PutProductRequest putProductRequest = PutProductRequest.builder()
.productId(0L)
.productName("아리수")
.productWeight(5)
.productType("11과")
.productPrice(100_000)
.productStock(100)
.productStatus(ProductStatus.ON_SALE)
.build();
//when
//then
Assertions.assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(() -> productService.putProduct(putProductRequest))
.withMessageContaining("유효하지 않은");
}
@Test
@DisplayName("상풍 수정에 성공한다.")
void putProduct() {
//given
PostProductRequest productRequest = PostProductRequest.builder()
.productName("아리수")
.productWeight(5)
.productType("11과")
.productPrice(100_000)
.productStock(100)
.build();
ProductEntity saveProduct = productRepository.save(productRequest.toProductEntity());
PutProductRequest putProductRequest = PutProductRequest.builder()
.productId(saveProduct.getProductId())
.productName("아리수")
.productWeight(5)
.productType("11과")
.productPrice(200_000)
.productStock(100)
.productStatus(ProductStatus.ON_SALE)
.build();
//when
PutProductResponse putProductResponse = productService.putProduct(putProductRequest);
//then
ProductEntity productEntity = productRepository.findById(saveProduct.getProductId()).get();
Assertions.assertThat(putProductResponse.productPrice()).isEqualTo(200_000);
Assertions.assertThat(productEntity.getProductPrice()).isEqualTo(200_000);
}
}
마지막으로 실패하는 케이스와 성공하는 케이스를 간단하게 테스트하였다.
✅ 프로젝트를 하다가 놓친 부분...;;
테스트 코드를 작성하다 보니 domain 쪽 메서드들을 테스트하지 않고 있다는걸 깨달았다. jacoco 설정을 바꾸고 domain쪽도 unit test code로 작성하여 테스트를 진행할 수 있도록 수정해야겠다.
728x90
반응형