diff --git a/build.gradle b/build.gradle index a2fae66..ae12b71 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ dependencies { implementation 'org.springframework.cloud:spring-cloud-aws-messaging:2.2.4.RELEASE' implementation 'org.springframework.kafka:spring-kafka' implementation 'software.amazon.awssdk:sns:2.21.37' - implementation 'io.github.lotteon-maven:blooming-blooms-utils:202401091420' + implementation 'io.github.lotteon-maven:blooming-blooms-utils:202401100155' // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop implementation 'org.springframework.boot:spring-boot-starter-aop:2.7.17' @@ -54,6 +54,11 @@ dependencies { implementation("it.ozimov:embedded-redis:0.7.2") implementation 'org.redisson:redisson-spring-boot-starter:3.17.0' + // testcontainers + testImplementation "org.junit.jupiter:junit-jupiter:5.8.1" + testImplementation "org.testcontainers:testcontainers:1.17.6" + testImplementation "org.testcontainers:junit-jupiter:1.17.6" + testImplementation 'org.mockito:mockito-core:4.8.0' } @@ -88,7 +93,7 @@ jacocoTestCoverageVerification { value = 'COVEREDRATIO' minimum = 0.80 } - excludes = ["*.mapper*", "**.emitter.**", "**.infrastructure.**"] + excludes = ["*.mapper*", "**.emitter.**", "**.infrastructure.**", "**.aop.**", "**.annotation.**"] } } } @@ -102,7 +107,9 @@ test { "**/handler/**", "**/common/**", "**/api/**", - "**/emitter/**" + "**/emitter/**", + "**/aop/**", + "**/annotation/**" ] } useJUnitPlatform() @@ -126,7 +133,9 @@ jacocoTestReport { "**/*mapper*", "**/*Config*", "**/*Dto*", - "**/emitter/**" + "**/emitter/**", + "**/aop/**", + "**/annotation/**" ] + Qdomains) }) ) diff --git a/src/main/java/kr/bb/notification/common/annotation/DuplicateEventHandleAnnotation.java b/src/main/java/kr/bb/notification/common/annotation/DuplicateEventHandleAnnotation.java index 1783f4c..03f3886 100644 --- a/src/main/java/kr/bb/notification/common/annotation/DuplicateEventHandleAnnotation.java +++ b/src/main/java/kr/bb/notification/common/annotation/DuplicateEventHandleAnnotation.java @@ -9,6 +9,4 @@ @Retention(RetentionPolicy.RUNTIME) public @interface DuplicateEventHandleAnnotation { String getEventType(); - - long getTtl() default 1L; } diff --git a/src/main/java/kr/bb/notification/common/aop/DuplicateEventHandlerAop.java b/src/main/java/kr/bb/notification/common/aop/DuplicateEventHandlerAop.java index af19e9a..c46eb99 100644 --- a/src/main/java/kr/bb/notification/common/aop/DuplicateEventHandlerAop.java +++ b/src/main/java/kr/bb/notification/common/aop/DuplicateEventHandlerAop.java @@ -10,6 +10,7 @@ import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; +import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; @@ -20,6 +21,9 @@ public class DuplicateEventHandlerAop { private final RedisTemplate redisTemplate; + @Value("${cache.expire}") + private int expire; + @Pointcut("@annotation(duplicateEventHandleAnnotation)") public void duplicateEvent(DuplicateEventHandleAnnotation duplicateEventHandleAnnotation) {} @@ -35,14 +39,14 @@ public Object duplicateEventHandlerAop( String id = String.valueOf(notifyData.getId()); Role role = notifyData.getRole(); String eventType = duplicateEventHandleAnnotation.getEventType(); - long ttl = duplicateEventHandleAnnotation.getTtl(); String generateEventId = eventId + ":" + id + ":" + role + ":" + eventType; Object event = redisTemplate.opsForValue().get(generateEventId); log.info("event id : " + generateEventId); + if (event == null) { redisTemplate.opsForValue().set(generateEventId, eventType); - redisTemplate.expire(generateEventId, ttl, TimeUnit.MINUTES); // TODO: test 후 Days로 변경 + redisTemplate.expire(generateEventId, expire, TimeUnit.MINUTES); Object[] args = joinPoint.getArgs(); diff --git a/src/main/java/kr/bb/notification/domain/notification/infrastructure/message/NotificationSQSListener.java b/src/main/java/kr/bb/notification/domain/notification/infrastructure/message/NotificationSQSListener.java index bb9cfcb..9fe0953 100644 --- a/src/main/java/kr/bb/notification/domain/notification/infrastructure/message/NotificationSQSListener.java +++ b/src/main/java/kr/bb/notification/domain/notification/infrastructure/message/NotificationSQSListener.java @@ -125,8 +125,7 @@ public void consumeNewOrderNotificationQueue( PublishNotificationInformation.makePublishNotificationInformation( NewOrderEventItem.getNotificationURL(item.getOrderType()), NewOrderEventItem.getNotificationKind(item.getOrderType()), - Role.MANAGER, - "new-order-queue")); + Role.MANAGER)); notificationActionHelper.publishNewOrderNotification(notificationData); }); diff --git a/src/test/java/config/RedisTestConfig.java b/src/test/java/config/RedisTestConfig.java new file mode 100644 index 0000000..db6e95b --- /dev/null +++ b/src/test/java/config/RedisTestConfig.java @@ -0,0 +1,30 @@ +package config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.GenericContainer; + +@ActiveProfiles("test") +@Configuration +public class RedisTestConfig { + static final String REDIS_IMAGE = "redis:6-alpine"; + static final GenericContainer REDIS_CONTAINER; + + static { + REDIS_CONTAINER = + new GenericContainer<>(REDIS_IMAGE) + .withExposedPorts(6379) + .withCommand("--requirepass", "123456") + .withReuse(true); + REDIS_CONTAINER.start(); + } + + @DynamicPropertySource + public static void overrideProps(DynamicPropertyRegistry registry) { + registry.add("spring.redis.host", REDIS_CONTAINER::getHost); + registry.add("spring.redis.port", () -> "" + REDIS_CONTAINER.getMappedPort(6379)); + registry.add("spring.redis.password", () -> "123456"); + } +} diff --git a/src/test/java/config/TestENV.java b/src/test/java/config/TestENV.java new file mode 100644 index 0000000..88e1426 --- /dev/null +++ b/src/test/java/config/TestENV.java @@ -0,0 +1,19 @@ +package config; + +import kr.bb.notification.common.annotation.DuplicateEventHandleAnnotation; +import kr.bb.notification.common.aop.DuplicateEventHandlerAop; +import org.redisson.api.RedissonClient; +import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.transaction.annotation.Transactional; + +@SpringBootTest +@Transactional +@ActiveProfiles("test") +public class TestENV { + @MockBean private RedissonClient redissonClient; + @MockBean private DuplicateEventHandlerAop duplicateEventHandlerAop; + @MockBean private MetricsAutoConfiguration metricsAutoConfiguration; +} diff --git a/src/test/java/kr/bb/notification/domain/notification/facade/NotificationQueryFacadeHandlerTest.java b/src/test/java/kr/bb/notification/domain/notification/facade/NotificationQueryFacadeHandlerTest.java index 4d3ea5e..5d487ae 100644 --- a/src/test/java/kr/bb/notification/domain/notification/facade/NotificationQueryFacadeHandlerTest.java +++ b/src/test/java/kr/bb/notification/domain/notification/facade/NotificationQueryFacadeHandlerTest.java @@ -3,6 +3,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import bloomingblooms.domain.notification.Role; +import config.TestENV; import java.util.ArrayList; import java.util.List; import kr.bb.notification.domain.notification.entity.MemberNotification; @@ -21,7 +22,7 @@ @SpringBootTest @Transactional -class NotificationQueryFacadeHandlerTest { +class NotificationQueryFacadeHandlerTest extends TestENV { @MockBean SimpleMessageListenerContainer simpleMessageListenerContainer; @Autowired NotificationJpaRepository notificationJpaRepository; diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml index de4c4fe..485ce8f 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application.yml @@ -1,4 +1,8 @@ spring: + redis: + host: localhost + port: 6379 + password: 123456 cloud: config: enabled: false