Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions src/main/java/com/example/demo/model/Cart.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.example.demo.model;

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

public class Cart {

private List<LineItem> lineItems;
private int totalQuantity;

public Cart(List<LineItem> lineItems) {
this.lineItems = new ArrayList<>(lineItems);
calculateTotalQuantity();
}

public List<LineItem> getLineItems() {
return Collections.unmodifiableList(lineItems);
}

public int getTotalQuantity() {
return totalQuantity;
}

public void addProduct(ProductId productId, ProductOption productOption, int quantity) {


LineItem lineItem = findLineItem(productId, productOption);

if (lineItem != null) {
lineItem.addQuantity(quantity, productOption);
calculateTotalQuantity();
checkValidQuantity();
return;
}

lineItem = new LineItem(productId, productOption, quantity);
lineItems.add(lineItem);
calculateTotalQuantity();
checkValidQuantity();
}

public void checkValidQuantity() {
if (totalQuantity > 20) {
throw new IllegalArgumentException("담을수 있는 수량을 초과했습니다.");
}
}

private void calculateTotalQuantity() {
this.totalQuantity = lineItems.stream()
.mapToInt(LineItem::getQuantity)
.sum();
}


private LineItem findLineItem(ProductId productId, ProductOption productOption) {
return lineItems.stream()
.filter(lineItem ->
lineItem.isSameProduct(productId,productOption))
.findFirst()
.orElse(null);
}

}
35 changes: 35 additions & 0 deletions src/main/java/com/example/demo/model/LineItem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.example.demo.model;


public class LineItem {

private final LineItemId id;
private final ProductId productId;
private final ProductOption productOption;

private int quantity;


public LineItem(ProductId productId, ProductOption productOption, int quantity) {
this.id = LineItemId.generate();
this.productId = productId;
this.productOption = productOption;
this.quantity = quantity;
}

public int getQuantity() {
return quantity;
}


public void addQuantity(int quantity, ProductOption productOption) {
if(!this.productOption.equals(productOption)) {
return;
}
this.quantity += quantity;
}

public boolean isSameProduct(ProductId productId, ProductOption productOption) {
return this.productId.equals(productId) && this.productOption.equals(productOption);
}
}
12 changes: 12 additions & 0 deletions src/main/java/com/example/demo/model/LineItemId.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.example.demo.model;

import java.util.UUID;

public record LineItemId(
String id
) {

public static LineItemId generate() {
return new LineItemId("lineItemId-" + UUID.randomUUID());
}
}
34 changes: 34 additions & 0 deletions src/main/java/com/example/demo/model/Product.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.example.demo.model;

public class Product {

private ProductId id;
private String name;
private int price;

public Product(ProductId id, String name, int price) {
this.id = id;
this.name = name;
this.price = price;
}

public ProductId getId() {
return id;
}

public String getName() {
return name;
}

public int getPrice() {
return price;
}

public void changePrice(int price) {
this.price = price;
}

public void changeName(String name) {
this.name = name;
}
}
6 changes: 6 additions & 0 deletions src/main/java/com/example/demo/model/ProductId.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.example.demo.model;

public record ProductId (
String id
){
}
7 changes: 7 additions & 0 deletions src/main/java/com/example/demo/model/ProductOption.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.demo.model;

public record ProductOption(
String color,
String size
) {
}
101 changes: 101 additions & 0 deletions src/test/java/com/example/demo/model/CartTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package com.example.demo.model;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

class CartTest {

private Product product1;
private Product product2;
private ProductOption productOption1;
private ProductOption productOption2;

@BeforeEach
void setUp() {
product1 = new Product(new ProductId("product-1"), "product #1", 5000);
product2 = new Product(new ProductId("product-2"), "product #2", 3000);

productOption1 = new ProductOption("red", "M");
productOption2 = new ProductOption("black", "L");
}

@Test
@DisplayName("빈 장바구니의 수량은 0이다.")
void cartTotalQuantityIsZero() {
Cart cart = new Cart(List.of());

assertThat(cart.getTotalQuantity()).isEqualTo(0);
}

@Test
@DisplayName("빈 장바구니에 물건 추가하면 장바구니의 전체수량은 추가한 수량과 같다.")
void addProduct() {
Cart cart = new Cart(List.of());

int quantity = 1;
cart.addProduct(product1.getId(), productOption1, quantity);

assertThat(cart.getTotalQuantity()).isEqualTo(quantity);
}

@Test
@DisplayName("장바구니에 이미 있는 물건 추가하면 전체 수량은 이미 있던 수량과 새로 추가하는 수량의 합이다.")
void addExistingProduct() {

int oldQuantity = 1;
Cart cart = new Cart(List.of(
createLineItem(product1, productOption1, oldQuantity)
));

int newQuantity = 1;
cart.addProduct(product1.getId(), productOption1, newQuantity);

assertThat(cart.getLineItems()).hasSize(1);
assertThat(cart.getTotalQuantity()).isEqualTo(oldQuantity + newQuantity);
}

@Test
@DisplayName("장바구니에 새로운 있는 물건 추가하면 전체 수량은 이미 있던 물건의 수량과 " +
"새로 추가하는 물건의 수량의 합이다.")
void addNewProduct() {

int oldQuantity = 1;
Cart cart = new Cart(List.of(
createLineItem(product2, productOption2, oldQuantity)
));

int newQuantity = 1;
cart.addProduct(product1.getId(), productOption1, newQuantity);

assertThat(cart.getLineItems()).hasSize(2);
assertThat(cart.getTotalQuantity()).isEqualTo(oldQuantity + newQuantity);
}

@Test
@DisplayName("전체 장바구니의 수량이 20개가 넘어가면 예외가 발생한다.")
void totalQuantityCanNotOverLimit() {
Cart cart = new Cart(List.of(
createLineItem(product1, productOption1, 19)
));

int newQuantity = 5;

assertThatThrownBy(
() -> cart.addProduct(product1.getId(), productOption1, newQuantity)
).isInstanceOf(IllegalArgumentException.class);

}



private LineItem createLineItem(Product product, ProductOption productOption, int quantity) {
return new LineItem(product.getId(), productOption, quantity);
}

}
30 changes: 30 additions & 0 deletions src/test/java/com/example/demo/model/LineItemIdTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.example.demo.model;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;

class LineItemIdTest {

@Test
@DisplayName("같은 값이면 같은 객체로 취급된다.")
void sameLineItemId() {
LineItemId id1 = new LineItemId("LineItem-1");
LineItemId id2 = new LineItemId("LineItem-1");

assertThat(id1).isEqualTo(id2);
}

@Test
@DisplayName("generate()를 사용하면 서로다른 아이디가 생성된다.")
void lineItemIdIsUnique() {
LineItemId id1 = LineItemId.generate();
LineItemId id2 = LineItemId.generate();

assertThat(id1).isNotEqualTo(id2);
}


}
42 changes: 42 additions & 0 deletions src/test/java/com/example/demo/model/LineItemTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.example.demo.model;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;


class LineItemTest {

@Test
@DisplayName("같은 상품과 옵션일 경우, 수량을 추가할 수 있어야 한다.")
void isSameProduct(){
ProductId productId = new ProductId("productId");
ProductOption productOption = new ProductOption("red", "M");
int quantity = 1;
int delta = 5;

LineItem lineItem = new LineItem(productId, productOption, quantity);
lineItem.addQuantity(delta, productOption);

assertThat(lineItem.isSameProduct(productId, new ProductOption("red", "M"))).isTrue();
assertThat(lineItem.getQuantity()).isEqualTo(quantity + delta);

}

@Test
@DisplayName("같은 상품이라도 옵션이 다르면, 수량은 추가되지 않는다.")
void sameProductAndDifferentOption(){
ProductId productId = new ProductId("productId");
ProductOption productOption = new ProductOption("red", "M");
int quantity = 1;
int delta = 5;
LineItem lineItem = new LineItem(productId, productOption, quantity);

ProductOption productOption2 = new ProductOption("black", "M");
lineItem.addQuantity(delta, productOption2);

assertThat(lineItem.isSameProduct(productId, productOption2)).isFalse();
assertThat(lineItem.getQuantity()).isEqualTo(quantity);
}
}
20 changes: 20 additions & 0 deletions src/test/java/com/example/demo/model/ProductIdTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.example.demo.model;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;

class ProductIdTest {

@Test
@DisplayName("같은 값이면 같은 객체로 취급된다.")
void sameProductId() {
ProductId id1 = new ProductId("productId-1");
ProductId id2 = new ProductId("productId-1");

assertThat(id1).isEqualTo(id2);
}

}
28 changes: 28 additions & 0 deletions src/test/java/com/example/demo/model/ProductOptionTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.example.demo.model;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

class ProductOptionTest {

@Test
@DisplayName("값이 같으면 같은 객체로 취급된다.")
void sameValue() {
ProductOption option1 = new ProductOption("red", "M");
ProductOption option2 = new ProductOption("red", "M");

assertThat(option1).isEqualTo(option2);
}

@Test
@DisplayName("값이 다르면 다른 객체로 취급된다.")
void differentValue() {
ProductOption option1 = new ProductOption("red", "M");
ProductOption option2 = new ProductOption("black", "M");

assertThat(option1).isNotEqualTo(option2);
}

}
Loading