Skip to content

Commit edc5f81

Browse files
committed
feat: JPA @table 설정 추가 및 멱등성 통합 테스트 구현
- `OutboxEvent`, `ProductMetrics`, `EventHandled` 엔티티에 @table 애너테이션 추가. - `IdempotencyIntegrationTest` 구현으로 중복 이벤트 처리 검증.
1 parent 47333f2 commit edc5f81

4 files changed

Lines changed: 61 additions & 0 deletions

File tree

apps/commerce-api/src/main/java/com/loopers/domain/event/OutboxEvent.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
import jakarta.persistence.GeneratedValue;
66
import jakarta.persistence.GenerationType;
77
import jakarta.persistence.Id;
8+
import jakarta.persistence.Table;
89
import java.time.LocalDateTime;
910
import lombok.Getter;
1011
import lombok.NoArgsConstructor;
1112

1213
@Entity
1314
@Getter
15+
@Table(name = "outbox_event")
1416
@NoArgsConstructor
1517
public class OutboxEvent {
1618

apps/commerce-streamer/src/main/java/com/loopers/domain/event/EventHandled.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
import jakarta.persistence.Entity;
44
import jakarta.persistence.Id;
5+
import jakarta.persistence.Table;
56
import java.time.LocalDateTime;
67
import lombok.AccessLevel;
78
import lombok.Getter;
89
import lombok.NoArgsConstructor;
910

1011
@Entity
1112
@Getter
13+
@Table(name = "event_handled")
1214
@NoArgsConstructor(access = AccessLevel.PROTECTED)
1315
public class EventHandled {
1416

apps/commerce-streamer/src/main/java/com/loopers/domain/metrics/ProductMetrics.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
import jakarta.persistence.Entity;
44
import jakarta.persistence.Id;
5+
import jakarta.persistence.Table;
56
import java.time.LocalDateTime;
67
import lombok.AccessLevel;
78
import lombok.Getter;
89
import lombok.NoArgsConstructor;
910

1011
@Entity
1112
@Getter
13+
@Table(name = "product_metrics")
1214
@NoArgsConstructor(access = AccessLevel.PROTECTED)
1315
public class ProductMetrics {
1416

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.loopers.domain.metrics;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
5+
import com.loopers.event.SalesCountEvent;
6+
import com.loopers.infrastructure.ProductMetricsRepository;
7+
import com.loopers.utils.DatabaseCleanUp;
8+
import org.junit.jupiter.api.AfterEach;
9+
import org.junit.jupiter.api.DisplayName;
10+
import org.junit.jupiter.api.Test;
11+
import org.springframework.beans.factory.annotation.Autowired;
12+
import org.springframework.boot.test.context.SpringBootTest;
13+
14+
@SpringBootTest
15+
class IdempotencyIntegrationTest {
16+
17+
@Autowired
18+
private ProductMetricsService metricsService;
19+
20+
@Autowired
21+
private ProductMetricsRepository metricsRepository;
22+
23+
@Autowired
24+
private DatabaseCleanUp databaseCleanUp;
25+
26+
@AfterEach
27+
void tearDown() {
28+
databaseCleanUp.truncateAllTables();
29+
}
30+
31+
32+
@Test
33+
@DisplayName("중복 이벤트 수신 시에도 메트릭 수치는 단 한 번만 반영되어야 한다")
34+
void shouldHandleDuplicateEventIdempotently() {
35+
// Given: 동일한 ID를 가진 이벤트 준비
36+
Long productId = 99L;
37+
int salesQuantity = 2;
38+
39+
SalesCountEvent firstEvent = SalesCountEvent.of(productId, salesQuantity);
40+
41+
// When: 첫 번째 전송
42+
metricsService.processSalesCountEvent(firstEvent);
43+
44+
// Then: 수치 반영 확인
45+
int firstResult = metricsRepository.findById(productId).get().getSalesCount();
46+
assertThat(firstResult).isEqualTo(2);
47+
48+
// When: 동일 ID로 두 번째 전송 (Kafka 재전송 시나리오)
49+
metricsService.processSalesCountEvent(firstEvent);
50+
51+
// Then: 수치가 4가 아니라 여전히 2여야 함 (멱등성 성공)
52+
int secondResult = metricsRepository.findById(productId).get().getSalesCount();
53+
assertThat(secondResult).isEqualTo(2);
54+
}
55+
}

0 commit comments

Comments
 (0)