Skip to content
Open
Show file tree
Hide file tree
Changes from 11 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
4 changes: 4 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-validation")

//MongoDB
implementation("org.mongodb:mongodb-driver-core:5.2.0")
implementation("org.mongodb:mongodb-driver-sync:5.2.0")
Comment on lines +22 to +24
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

MongoDB 의존성 설정 개선이 필요합니다

Spring Boot 애플리케이션에서 MongoDB를 사용할 때는 직접 드라이버를 추가하는 것보다 spring-boot-starter-data-mongodb를 사용하는 것이 좋습니다. 이는 다음과 같은 이점이 있습니다:

  • Spring Data MongoDB의 고수준 추상화 제공
  • 자동 설정 지원
  • Spring Boot의 의존성 관리와 완벽한 통합

다음과 같이 수정하는 것을 추천드립니다:

-    //MongoDB
-    implementation("org.mongodb:mongodb-driver-core:5.2.0")
-    implementation("org.mongodb:mongodb-driver-sync:5.2.0")
+    implementation("org.springframework.boot:spring-boot-starter-data-mongodb")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
//MongoDB
implementation("org.mongodb:mongodb-driver-core:5.2.0")
implementation("org.mongodb:mongodb-driver-sync:5.2.0")
implementation("org.springframework.boot:spring-boot-starter-data-mongodb")


developmentOnly("org.springframework.boot:spring-boot-devtools")

testImplementation("org.springframework.boot:spring-boot-starter-test")
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/com/example/demo/Application.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
package com.example.demo;

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public MongoClient mongoClient(){
String mongoURL = "mongodb://localhost:27017";
return MongoClients.create(mongoURL);
}
Comment on lines +14 to +18
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

MongoDB 연결 구성의 개선이 필요합니다.

현재 구현에는 몇 가지 개선이 필요한 부분이 있습니다:

  1. 하드코딩된 MongoDB URL을 외부 설정으로 이동해야 합니다.
  2. 연결 오류 처리가 누락되어 있습니다.
  3. 다양한 환경(개발, 테스트, 운영)에 대한 고려가 필요합니다.

다음과 같이 개선하는 것을 추천드립니다:

+@Configuration
 public class Application {
     public static void main(String[] args) {
         SpringApplication.run(Application.class, args);
     }

+    @Value("${spring.data.mongodb.uri}")
+    private String mongodbUri;
+
     @Bean
     public MongoClient mongoClient(){
-        String mongoURL = "mongodb://localhost:27017";
-        return MongoClients.create(mongoURL);
+        try {
+            return MongoClients.create(mongodbUri);
+        } catch (Exception e) {
+            throw new MongoConnectionException("MongoDB 연결 중 오류가 발생했습니다", e);
+        }
     }
 }

그리고 application.properties (또는 application.yml)에 다음을 추가해주세요:

spring.data.mongodb.uri=mongodb://localhost:27017

💡 Codebase verification

MongoDB 연결 설정의 보안 및 환경 설정 개선이 필요합니다

현재 MongoDB 연결 설정에 다음과 같은 문제점들이 발견되었습니다:

  • MongoDB 연결 URL이 코드에 하드코딩되어 있어 환경별 설정 변경이 어렵습니다.
  • application.yaml에 MongoDB 관련 설정이 누락되어 있습니다.
  • 테스트 코드는 존재하지만 실제 운영 환경을 위한 설정이 부족합니다.

다음 사항들의 추가를 권장드립니다:

  • application.yaml에 MongoDB 연결 정보를 추가하고 환경별로 설정할 수 있도록 구성
  • 보안을 위해 인증 정보 추가
  • 연결 타임아웃, 풀 설정 등 운영에 필요한 세부 설정 추가

예시 설정:

spring:
  data:
    mongodb:
      uri: ${MONGODB_URI:mongodb://localhost:27017/demo}
      connection-timeout: 5000
      socket-timeout: 5000
🔗 Analysis chain

MongoDB 연결 설정 검증이 필요합니다.

현재 설정된 MongoDB 연결이 의도한 대로 작동하는지 확인이 필요합니다.

다음 스크립트를 실행하여 MongoDB 관련 설정을 확인해보세요:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# MongoDB 관련 설정 파일 확인
echo "MongoDB 설정 파일 검색 중..."
fd -e properties -e yml | xargs rg "mongodb://"

# MongoDB 관련 환경 설정 클래스 검색
echo "MongoDB 설정 클래스 검색 중..."
rg -l "MongoProperties|MongoClientSettings" 

Length of output: 201


Script:

#!/bin/bash
# MongoDB 관련 설정 파일 검색 (확장자 추가)
echo "MongoDB 설정 파일 검색 중..."
fd -e properties -e yml -e yaml -e xml -e conf | xargs rg -i "mongo|mongodb"

# application.properties/yml 파일 직접 확인
echo "Application 설정 파일 확인 중..."
fd "application\.(properties|ya?ml)$"

# MongoDB 관련 Java 설정 클래스 검색
echo "MongoDB 설정 클래스 검색 중..."
rg -t java "import.*mongo" -A 5

# MongoDB 연결 관련 코드 검색
echo "MongoDB 연결 코드 검색 중..."
ast-grep --pattern 'mongoClient($$$) {
  $$$
}'

Length of output: 2010


Script:

#!/bin/bash
# application.yaml 파일의 내용 확인
echo "application.yaml 내용 확인:"
cat src/main/resources/application.yaml

# MongoDB 테스트 코드 확인
echo "MongoDB 테스트 코드 확인:"
cat src/test/java/com/example/demo/MongoDbTest.java

# MongoDB 관련 다른 설정이나 프로퍼티 검색
echo "추가 MongoDB 설정 검색:"
rg -g "!*.{class,jar}" -i "spring\.data\.mongodb|mongodb\." 

Length of output: 2233

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.demo.exceptions;

public class ExceedTotalQuantity extends RuntimeException {
public ExceedTotalQuantity(String message){
super(message);
}
}
80 changes: 80 additions & 0 deletions src/main/java/com/example/demo/models/Cart.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.example.demo.models;

import com.example.demo.exceptions.ExceedTotalQuantity;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class Cart {

private final List<CartItem> cartItems;
private int totalQuantity;

public Cart() {
this.cartItems = new ArrayList<>();
this.totalQuantity = 0;
}

public void checkTotalQuantity(int quantity) {
if (this.totalQuantity + quantity > 20) {
throw new ExceedTotalQuantity("장바구니 총 합계는 20을 넘길 수 없습니다.");
}
}

public void addCartItem(ProductId productId, int quantity) {

checkTotalQuantity(quantity);

Optional<CartItem> existingCartItem = findCartItem(productId);
if (existingCartItem.isPresent()) {
CartItem cartItem = existingCartItem.get();
cartItem.addQuantity(quantity);
} else {
addNewCartItem(productId, quantity);
}

this.totalQuantity += quantity;

}
Comment on lines +24 to +38
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

수량 검증 및 동시성 처리가 필요합니다

  1. 음수 수량에 대한 검증이 없습니다.
  2. totalQuantity 업데이트 시 동시성 문제가 발생할 수 있습니다.
  3. 메서드가 다소 긴 편이니 책임을 분리하면 좋을 것 같습니다.
public void addCartItem(ProductId productId, int quantity) {
+    if (quantity <= 0) {
+        throw new IllegalArgumentException("수량은 0보다 커야 합니다.");
+    }

-    checkTotalQuantity(quantity);
+    validateQuantityLimit(quantity);

    Optional<CartItem> existingCartItem = findCartItem(productId);
-    if (existingCartItem.isPresent()) {
-        CartItem cartItem = existingCartItem.get();
-        cartItem.addQuantity(quantity);
-    } else {
-        addNewCartItem(productId, quantity);
-    }
+    synchronized(this) {
+        if (existingCartItem.isPresent()) {
+            CartItem cartItem = existingCartItem.get();
+            cartItem.addQuantity(quantity);
+        } else {
+            addNewCartItem(productId, quantity);
+        }
+        this.totalQuantity += quantity;
+    }
-    this.totalQuantity += quantity;
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public void addCartItem(ProductId productId, int quantity) {
checkTotalQuantity(quantity);
Optional<CartItem> existingCartItem = findCartItem(productId);
if (existingCartItem.isPresent()) {
CartItem cartItem = existingCartItem.get();
cartItem.addQuantity(quantity);
} else {
addNewCartItem(productId, quantity);
}
this.totalQuantity += quantity;
}
public void addCartItem(ProductId productId, int quantity) {
if (quantity <= 0) {
throw new IllegalArgumentException("수량은 0보다 커야 합니다.");
}
validateQuantityLimit(quantity);
Optional<CartItem> existingCartItem = findCartItem(productId);
synchronized(this) {
if (existingCartItem.isPresent()) {
CartItem cartItem = existingCartItem.get();
cartItem.addQuantity(quantity);
} else {
addNewCartItem(productId, quantity);
}
this.totalQuantity += quantity;
}
}


private void addNewCartItem(ProductId productId, int quantity) {
if (productId == null) {
throw new IllegalArgumentException("상품 ID는 null일 수 없습니다.");
}
CartItemId cartItemId = new CartItemId();
Product product = new Product(productId);
CartItem newCartItem = new CartItem(cartItemId, product, quantity);
cartItems.add(newCartItem);
}

private Optional<CartItem> findCartItem(ProductId productId) {
return cartItems.stream()
.filter(cartItem -> {
Product product = cartItem.getProduct();
return product != null &&
product.productId().equals(productId);
})
.findFirst();
}

public List<CartItem> getCartList() {
return cartItems;
}

public void madeCartZero() {
this.totalQuantity = 0;
this.cartItems.clear();
}

public int getTotalQuantity() {
return totalQuantity;
}

@Override
public String toString() {
return "Cart{" +
"cartItems=" + cartItems +
", totalQuantity=" + totalQuantity +
'}';
}
}
64 changes: 64 additions & 0 deletions src/main/java/com/example/demo/models/CartItem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.example.demo.models;

import java.util.Objects;

public class CartItem {

private final CartItemId id;
private final Product product;
private int quantity;

Comment on lines +5 to +10
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

필드 유효성 검증 추가 필요

필수 필드에 대한 유효성 검증이 누락되어 있습니다. 다음과 같은 개선사항을 제안드립니다:

  • quantity 필드에 최소값 검증 추가
  • product와 id 필드에 @NotNull 어노테이션 추가
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;

 public class CartItem {
-    private final CartItemId id;
-    private final Product product;
-    private int quantity;
+    @NotNull
+    private final CartItemId id;
+    @NotNull
+    private final Product product;
+    @Min(value = 1, message = "수량은 1 이상이어야 합니다")
+    private int quantity;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public class CartItem {
private final CartItemId id;
private final Product product;
private int quantity;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
public class CartItem {
@NotNull
private final CartItemId id;
@NotNull
private final Product product;
@Min(value = 1, message = "수량은 1 이상이어야 합니다")
private int quantity;

public CartItem(CartItemId id, Product product, int quantity) {
if (id == null) {
throw new IllegalArgumentException("id는 null일 수 없습니다");
}
if (product == null) {
throw new IllegalArgumentException("product는 null일 수 없습니다");
}
if (quantity < 1) {
throw new IllegalArgumentException("수량은 1 이상이어야 합니다");
}
this.id = id;
this.product = product;
this.quantity = quantity;
}

public void addQuantity(int quantity) {
if (quantity < 0) {
throw new IllegalArgumentException("추가할 수량은 0 이상이어야 합니다");
}
this.quantity += quantity;
}

public Product getProduct() {
return product;
}

public int getQuantity() {
return quantity;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CartItem cartItem = (CartItem) o;
return id.equals(cartItem.id);
}

@Override
public int hashCode() {
return Objects.hash(id);
}

@Override
public String toString() {
return "CartItem{"
+ "id="
+ id
+ ", product="
+ product
+ ", quantity="
+ quantity + "}";
}
}
9 changes: 9 additions & 0 deletions src/main/java/com/example/demo/models/CartItemId.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.example.demo.models;

public record CartItemId(
String id
) {
public CartItemId(){
this(new GenerateId().id());
}
Comment on lines +6 to +8
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

🛠️ Refactor suggestion

ID 생성 로직 검증 완료 및 개선 권장

GenerateId와 IdGenerator 클래스의 구현을 확인한 결과, 다음과 같은 개선이 필요합니다:

  1. IdGenerator는 현재 시간(yyyyMMddHHmm)과 UUID 조합으로 ID를 생성하고 있어 기본적으로 null이 반환될 가능성은 낮습니다. 하지만 견고성을 위해 검증 로직 추가가 권장됩니다.
  2. 원래 제안된 수정사항이 여전히 유효합니다.

수정 제안:

public CartItemId(){
    String generatedId = new GenerateId().id();
    if (generatedId == null || generatedId.trim().isEmpty()) {
        throw new IllegalStateException("장바구니 아이템 ID가 올바르게 생성되지 않았습니다.");
    }
    this(generatedId);
}
🔗 Analysis chain

GenerateId 클래스 사용 및 유효성 검사 확인이 필요합니다.

다음 사항들을 확인해 주시기 바랍니다:

  1. GenerateId 클래스가 올바르게 구현되어 있는지 확인
  2. 생성된 ID가 null이 아님을 보장하는 검증 로직 추가 필요

다음과 같이 수정하는 것을 제안드립니다:

 public CartItemId(){
-    this(new GenerateId().id());
+    String generatedId = new GenerateId().id();
+    if (generatedId == null || generatedId.trim().isEmpty()) {
+        throw new IllegalStateException("장바구니 아이템 ID가 올바르게 생성되지 않았습니다.");
+    }
+    this(generatedId);
 }

GenerateId 클래스 구현을 확인하기 위해 다음 스크립트를 실행합니다:


Let me try a different search pattern to locate the GenerateId implementation.


Let me check the implementation of IdGenerator to complete the verification.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# GenerateId 클래스 구현 확인
echo "Searching for GenerateId class implementation..."
rg -l "class GenerateId"

# ID 생성 메서드 구현 확인
echo "Checking ID generation implementation..."
ast-grep --pattern 'class GenerateId {
  $$$
  $_ id() {
    $$$
  }
  $$$
}'

Length of output: 304


Script:

#!/bin/bash
# Search for GenerateId class with broader pattern
echo "Searching for GenerateId class with broader pattern..."
rg -A 5 "GenerateId"

# Search for files containing 'id' method
echo "Searching for files with id method..."
rg -A 3 "id\(\)"

Length of output: 2460


Script:

#!/bin/bash
# Check IdGenerator implementation
echo "Checking IdGenerator implementation..."
rg -A 10 "class IdGenerator"

# Check if there are any existing null checks
echo "Checking for null checks in related files..."
rg -A 3 "null|isEmpty|isBlank" src/main/java/com/example/demo/models/

Length of output: 1250

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

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

public record GenerateId(
String id
) {

public GenerateId() {
this(new IdGenerator().generateId());
}
}

class IdGenerator {

public String generateId() {
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("yyyyMMddHHmm");
String dateTime = now.format(formatter);
String shortUUID = UUID.randomUUID().toString().substring(0, 4);

return dateTime + shortUUID;
}
}
Comment on lines +16 to +27
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

⚠️ Potential issue

ID 생성기 개선 제안이 적절합니다

코드베이스 분석 결과, ProductId와 CartItemId에서 ID 생성기를 사용하고 있으며, 현재는 동시성 테스트나 대량 생성 시나리오가 구현되어 있지 않습니다. 하지만 제안된 개선사항들은 다음과 같은 이유로 여전히 유효합니다:

  1. 현재 테스트는 단순 생성 확인만 수행하고 있어, 실제 운영 환경에서 발생할 수 있는 ID 충돌 위험을 고려하지 않고 있습니다.
  2. ProductId와 CartItemId는 비즈니스적으로 중요한 식별자이므로, UUID 축소로 인한 충돌 가능성은 피해야 합니다.
  3. 향후 동시성 요구사항이 추가될 것을 고려하면, 제안된 개선사항들은 선제적인 안전장치가 될 것입니다.
🔗 Analysis chain

ID 생성 로직의 개선이 필요합니다.

현재 구현에는 다음과 같은 잠재적인 문제가 있습니다:

  1. UUID를 4자로 자르면 충돌 가능성이 높아집니다
  2. 타임스탬프가 분 단위까지만 포함되어 있어, 같은 분 내에 생성된 ID들의 충돌 가능성이 있습니다
  3. 동시성 처리가 되어있지 않습니다

다음과 같은 개선을 제안합니다:

 class IdGenerator {
+    private static final Object lock = new Object();
 
     public String generateId() {
-        LocalDateTime now = LocalDateTime.now();
-        DateTimeFormatter formatter =
-                DateTimeFormatter.ofPattern("yyyyMMddHHmm");
-        String dateTime = now.format(formatter);
-        String shortUUID = UUID.randomUUID().toString().substring(0, 4);
+        synchronized (lock) {
+            LocalDateTime now = LocalDateTime.now();
+            DateTimeFormatter formatter =
+                    DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
+            String dateTime = now.format(formatter);
+            String uuid = UUID.randomUUID().toString().replace("-", "");
 
-        return dateTime + shortUUID;
+            return dateTime + uuid;
+        }
     }
 }

다음 스크립트로 ID 생성 로직의 사용처를 확인해보겠습니다:


Let's check the usage of the ID generator in those files.


Let's check if there are any concurrent operations or batch processes that might create multiple IDs simultaneously.


Let's check the test files to see how the IDs are being tested, which might give us insight into the requirements for uniqueness and concurrency.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# ID 생성 로직을 사용하는 다른 클래스들을 검색
rg -l "new GenerateId\(\)" 

Length of output: 135


Script:

#!/bin/bash
# Check the content of files using the ID generator
rg -A 10 "new GenerateId\(\)" src/main/java/com/example/demo/models/CartItemId.java src/main/java/com/example/demo/models/ProductId.java

Length of output: 546


Script:

#!/bin/bash
# Search for any concurrent operations or batch processes
rg -l "CompletableFuture|ExecutorService|@Async|@Scheduled|parallel|Stream.parallel|newFixedThreadPool|newCachedThreadPool"

# Also check for any repository or service methods that might create products or cart items
rg -l "save.*Product|create.*Product|save.*CartItem|create.*CartItem"

Length of output: 312


Script:

#!/bin/bash
# Check the content of test files
rg -A 10 "class.*Test" src/test/java/com/example/demo/models/CartItemIdTest.java src/test/java/com/example/demo/models/ProductIdTest.java

Length of output: 1508


26 changes: 26 additions & 0 deletions src/main/java/com/example/demo/models/Product.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.example.demo.models;

import java.util.Objects;

public record Product (
ProductId productId
){

@Override
public String toString() {
return "{" + productId + "}";
}

@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Product product = (Product) obj;
return productId.equals(product.productId);
}

@Override
public int hashCode() {
return productId.hashCode();
}
}
11 changes: 11 additions & 0 deletions src/main/java/com/example/demo/models/ProductId.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.example.demo.models;

public record ProductId(
String id
) {

public ProductId() {
this(new GenerateId().id());
}

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

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import static org.assertj.core.api.Assertions.assertThat;

import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
public class MongoDbTest {

@Autowired
private MongoClient mongoClient;
Comment on lines +17 to +21
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

테스트 구성 개선 필요

MongoDB 테스트를 위해 더 가벼운 @DataMongoTest를 사용하고, 테스트 구성을 별도로 관리하는 것이 좋습니다.

다음과 같이 변경을 제안합니다:

-@SpringBootTest
+@DataMongoTest
+@TestPropertySource(properties = {
+    "spring.data.mongodb.uri=mongodb://localhost:27017/test-db"
+})
 public class MongoDbTest {

Committable suggestion skipped: line range outside the PR's diff.


@Test
public void testMongoClientBean() {
// MongoClient 빈이 주입되었는지 확인
assertThat(mongoClient).isNotNull();
}
@Test
void readProducts() {
// 1. DB 서버 접속 간단확인
String mongoDatabase = "demo";

// 2. 데이터 베이스 선택 -> demo
MongoDatabase database = mongoClient.getDatabase(mongoDatabase);

// 3. collection에서 목록 열기 -> products
MongoCollection<Document> collection =
database.getCollection("products");

List<Document> documents = new ArrayList<>();
collection.find().into(documents);

documents.forEach(document -> {
System.out.println(document.getString("name"));
System.out.println(document.getInteger("price"));
});
}
Comment on lines +29 to +47
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

테스트 메소드 개선 필요

현재 구현에는 몇 가지 개선이 필요한 부분이 있습니다:

  1. 하드코딩된 값들
  2. 예외 처리 부재
  3. System.out.println 사용
  4. 테스트 데이터 관리 부재

다음과 같이 개선을 제안합니다:

+@Value("${spring.data.mongodb.database}")
+private String databaseName;
+
+@BeforeEach
+void setUp() {
+    // 테스트 데이터 설정
+    MongoDatabase database = mongoClient.getDatabase(databaseName);
+    MongoCollection<Document> collection = database.getCollection("products");
+    collection.insertMany(Arrays.asList(
+        new Document("name", "테스트 상품1").append("price", 1000),
+        new Document("name", "테스트 상품2").append("price", 2000)
+    ));
+}
+
+@AfterEach
+void tearDown() {
+    // 테스트 데이터 정리
+    mongoClient.getDatabase(databaseName)
+        .getCollection("products")
+        .drop();
+}
+
 @Test
-void readProducts() {
-    // 1. DB 서버 접속 간단확인
-    String mongoDatabase = "demo";
-
-    // 2. 데이터 베이스 선택 -> demo
-    MongoDatabase database = mongoClient.getDatabase(mongoDatabase);
-
-    // 3. collection에서 목록 열기 -> products
-    MongoCollection<Document> collection =
-            database.getCollection("products");
-
-    List<Document> documents = new ArrayList<>();
-    collection.find().into(documents);
-
-    documents.forEach(document -> {
-        System.out.println(document.getString("name"));
-        System.out.println(document.getInteger("price"));
-    });
+void readProducts() throws Exception {
+    // given
+    MongoCollection<Document> collection = mongoClient
+        .getDatabase(databaseName)
+        .getCollection("products");
+    
+    // when
+    List<Document> documents = collection.find()
+        .into(new ArrayList<>());
+    
+    // then
+    assertThat(documents).hasSize(2);
+    assertThat(documents.get(0))
+        .extracting("name", "price")
+        .containsExactly("테스트 상품1", 1000);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
void readProducts() {
// 1. DB 서버 접속 간단확인
String mongoDatabase = "demo";
// 2. 데이터 베이스 선택 -> demo
MongoDatabase database = mongoClient.getDatabase(mongoDatabase);
// 3. collection에서 목록 열기 -> products
MongoCollection<Document> collection =
database.getCollection("products");
List<Document> documents = new ArrayList<>();
collection.find().into(documents);
documents.forEach(document -> {
System.out.println(document.getString("name"));
System.out.println(document.getInteger("price"));
});
}
@Value("${spring.data.mongodb.database}")
private String databaseName;
@BeforeEach
void setUp() {
// 테스트 데이터 설정
MongoDatabase database = mongoClient.getDatabase(databaseName);
MongoCollection<Document> collection = database.getCollection("products");
collection.insertMany(Arrays.asList(
new Document("name", "테스트 상품1").append("price", 1000),
new Document("name", "테스트 상품2").append("price", 2000)
));
}
@AfterEach
void tearDown() {
// 테스트 데이터 정리
mongoClient.getDatabase(databaseName)
.getCollection("products")
.drop();
}
@Test
void readProducts() throws Exception {
// given
MongoCollection<Document> collection = mongoClient
.getDatabase(databaseName)
.getCollection("products");
// when
List<Document> documents = collection.find()
.into(new ArrayList<>());
// then
assertThat(documents).hasSize(2);
assertThat(documents.get(0))
.extracting("name", "price")
.containsExactly("테스트 상품1", 1000);
}



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

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

class CartItemIdTest {
@Test
void createCartItemId(){
CartItemId id = new CartItemId();
System.out.println("Generated ID: " + id.id());
assertNotNull(id.id(), "ID should not be null");
}
Comment on lines +8 to +13
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

테스트 케이스 보완이 필요합니다.

현재 테스트는 ID가 null이 아닌지만 확인하고 있습니다. ID의 고유성이나 형식에 대한 추가 검증이 필요할 수 있습니다.

다음과 같은 추가 테스트 케이스를 제안합니다:

@Test
void createMultipleCartItemIds_ShouldGenerateUniqueIds() {
    CartItemId id1 = new CartItemId();
    CartItemId id2 = new CartItemId();
    
    assertNotEquals(id1.id(), id2.id(), "Generated IDs should be unique");
}

@Test
void generatedId_ShouldFollowExpectedFormat() {
    CartItemId id = new CartItemId();
    String generatedId = id.id();
    
    // ID 형식이 예상된 패턴을 따르는지 확인
    assertTrue(generatedId.matches("^[a-zA-Z0-9-]+$"), "ID should match expected format");
}

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

import static org.junit.jupiter.api.Assertions.*;

import java.util.ArrayList;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class CartItemTest {

private CartItem cartItem;
private CartItemId cartItemId;
private Product product;
private ProductId productId;
private ArrayList<Product> products;

@BeforeEach
void setUp() {
productId = new ProductId();
product = new Product(productId);

cartItemId = new CartItemId();
cartItem = new CartItem(cartItemId, product, 1);
}

@Test
void addQuantity() {
cartItem.addQuantity(1);
assertEquals(2, cartItem.getQuantity());
}
Comment on lines +26 to +30
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

중복된 테스트 케이스 통합 필요

addQuantity() 테스트와 addQuantity_WhenAddingPositiveNumber_ShouldIncreaseQuantity() 테스트가 동일한 시나리오를 검증하고 있습니다. 명확한 이름을 가진 후자의 테스트만 유지하는 것이 좋습니다.

-    @Test
-    void addQuantity() {
-        cartItem.addQuantity(1);
-        assertEquals(2, cartItem.getQuantity());
-    }

Also applies to: 32-35

@Test
void addQuantity_WhenAddingPositiveNumber_ShouldIncreaseQuantity() {
cartItem.addQuantity(1);
assertEquals(2, cartItem.getQuantity());
}

@Test
void addQuantity_WhenAddingNegativeNumber_ShouldThrowException() {
assertThrows(IllegalArgumentException.class, () -> cartItem.addQuantity(-1));
}

@Test
void addQuantity_WhenAddingZero_ShouldNotChangeQuantity() {
cartItem.addQuantity(0);
assertEquals(1, cartItem.getQuantity());
}
}
Loading