diff --git a/README.md b/README.md
index b9d04dd2..00b2da30 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,42 @@
-# moabam-BE
+## ๐ฅ MOABAM ์๋น์ค
+
+![img.png](readme-image/img.png)
+
+![img_1.png](readme-image/img_1.png)
+
+
+
+## ๐จโ๐จโ๐ง Backend Team ์๊ฐ
+
+| ๊น์๋ช
| ๊นํฌ๋น | ๋ฐ์ธ์ฐ(PO) | ์ ์ฌ์ค | ํํ์ค(SM) |
+|:------------------------------------------------------------------------------:|:------------------------------------------------------------------------------:|:------------------------------------------------------------------------------:|:------------------------------------------------------------------------------:|:------------------------------------------------------------------------------:|
+| DEVELOPER | DEVELOPER | DEVELOPER | DEVELOPER | DEVELOPER |
+| | | | | |
+| [ymkim97](https://github.com/ymkim97) | [kmebin](https://github.com/kmebin) | [parksey](https://github.com/parksey) | [DevUni](https://github.com/Shin-Jae-Yoon) | [HongDosan](https://github.com/HyuckJuneHong) |
+| ๋ฐฉ ๋๋ฉ์ธ, ๋ฃจํด ์ธ์ฆ(๋ฉ์ธ) | ์ํ ๋๋ฉ์ธ, ๊ฒฐ์ , ์๋ฌ ์๋ฆผ, BE ํ์ฅ | ํ์ ๋๋ฉ์ธ, ๋ญํน ์ด๋๋ฏผ ํ์ด์ง | ๋ฐฉ ๋๋ฉ์ธ, ๋ฃจํด ์ธ์ฆ(์๋ธ), ์ธํ๋ผ (AWS, CI/CD) | ์ฟ ํฐ ๋๋ฉ์ธ, ์๋ฆผ, ์ ์ฐฉ์ ์ด๋ฒคํธ, ์บ์ฑ |
+
+
+
+## ๊ณตํต ํ์
๋ฐฉ์
+
+![img.png](readme-image/ํ์
.png)
+
+## ์๋น์ค ์ํคํ
์ฒ
+
+![img.png](readme-image/์๋น์ค-์ํคํ
์ฒ.png)
+
+## CI/CD ํ์ดํ๋ผ์ธ
+
+![img.png](readme-image/ํ์ดํ๋ผ์ธ.png)
+
+## ์ปจ๋ฒค์
+
+![img_1.png](readme-image/์ปจ๋ฒค์
.png)
+
+## Config ๊ด๋ฆฌ
+
+![img.png](readme-image/์ฝํผ๊ทธ.png)
+
+## Test
+
+![img.png](readme-image/ํ
์คํธ.png)
diff --git a/build.gradle b/build.gradle
index c7f8c37e..63b52fa7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -15,14 +15,26 @@ java {
sourceCompatibility = '17'
}
+compileJava {
+ options.compilerArgs << '-parameters'
+ options.encoding = 'UTF-8'
+}
+
+compileTestJava {
+ options.compilerArgs << '-parameters'
+ options.encoding = 'UTF-8'
+}
+
ext {
snippetsDir = file('build/generated-snippets')
}
def querydslSrcDir = 'src/main/generated'
+
clean {
delete file(querydslSrcDir)
}
+
tasks.withType(JavaCompile) {
options.generatedSourceOutputDirectory = file(querydslSrcDir)
}
@@ -75,6 +87,9 @@ dependencies {
// Apache Commons Lang 3
implementation 'org.apache.commons:commons-lang3:3.13.0'
+ // Cache
+ implementation 'org.springframework.boot:spring-boot-starter-cache'
+
// Redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
@@ -134,28 +149,25 @@ jacocoTestReport {
afterEvaluate {
classDirectories.setFrom(
- files(classDirectories.files.collect {
- fileTree(dir: it, excludes: [
- "**/*Application*",
- "**/*Config*",
- "**/*Request*",
- "**/*Response*",
- "**/*Exception*",
- "**/*Mapper*",
- "**/*ErrorMessage*",
- "**/*DynamicQuery*",
- "**/*BaseTimeEntity*",
- "**/*HealthCheckController*",
- "**/*S3Manager*",
- ] + Qdomains)
- })
+ files(classDirectories.files.collect {
+ fileTree(dir: it, excludes: [
+ "**/*Application*",
+ "**/*Config*",
+ "**/*Request*",
+ "**/*Response*",
+ "**/*Exception*",
+ "**/*Mapper*",
+ "**/*ErrorMessage*",
+ "**/*DynamicQuery*",
+ "**/*BaseTimeEntity*",
+ "**/*HealthCheckController*",
+ "**/*S3Manager*",
+ ] + Qdomains)
+ })
)
}
}
-compileJava.options.encoding = 'UTF-8'
-compileTestJava.options.encoding = 'UTF-8'
-
tasks.withType(Checkstyle).configureEach {
reports {
xml.required = true
@@ -177,9 +189,9 @@ sonar {
property "sonar.host.url", "https://sonarcloud.io"
property 'sonar.coverage.jacoco.xmlReportPaths', 'build/reports/jacoco/test/jacocoTestReport.xml'
property 'sonar.coverage.exclusions', '**/test/**, **/Q*.java, **/*Doc*.java, **/resources/** ' +
- ',**/*Application*.java , **/*Config*.java, **/*Request*.java, **/*Response*.java ,**/*Exception*.java ' +
- ',**/*ErrorMessage*.java, **/*Mapper*.java, **/*DynamicQuery*, **/*BaseTimeEntity*, **/*HealthCheckController* ' +
- ', **/*S3Manager*.java'
+ ',**/*Application*.java , **/*Config*.java, **/*Request*.java, **/*Response*.java ,**/*Exception*.java ' +
+ ',**/*ErrorMessage*.java, **/*Mapper*.java, **/*DynamicQuery*, **/*BaseTimeEntity*, **/*HealthCheckController* ' +
+ ', **/*S3Manager*.java'
property 'sonar.java.checkstyle.reportPaths', 'build/reports/checkstyle/main.xml'
}
}
diff --git a/readme-image/img.png b/readme-image/img.png
new file mode 100644
index 00000000..42fda84d
Binary files /dev/null and b/readme-image/img.png differ
diff --git a/readme-image/img_1.png b/readme-image/img_1.png
new file mode 100644
index 00000000..911a57d3
Binary files /dev/null and b/readme-image/img_1.png differ
diff --git "a/readme-image/\354\204\234\353\271\204\354\212\244-\354\225\204\355\202\244\355\205\215\354\262\230.png" "b/readme-image/\354\204\234\353\271\204\354\212\244-\354\225\204\355\202\244\355\205\215\354\262\230.png"
new file mode 100644
index 00000000..a8400b13
Binary files /dev/null and "b/readme-image/\354\204\234\353\271\204\354\212\244-\354\225\204\355\202\244\355\205\215\354\262\230.png" differ
diff --git "a/readme-image/\354\273\250\353\262\244\354\205\230.png" "b/readme-image/\354\273\250\353\262\244\354\205\230.png"
new file mode 100644
index 00000000..c2b6cb3f
Binary files /dev/null and "b/readme-image/\354\273\250\353\262\244\354\205\230.png" differ
diff --git "a/readme-image/\354\275\230\355\224\274\352\267\270.png" "b/readme-image/\354\275\230\355\224\274\352\267\270.png"
new file mode 100644
index 00000000..c0cc64a9
Binary files /dev/null and "b/readme-image/\354\275\230\355\224\274\352\267\270.png" differ
diff --git "a/readme-image/\355\205\214\354\212\244\355\212\270.png" "b/readme-image/\355\205\214\354\212\244\355\212\270.png"
new file mode 100644
index 00000000..fb9929d1
Binary files /dev/null and "b/readme-image/\355\205\214\354\212\244\355\212\270.png" differ
diff --git "a/readme-image/\355\214\214\354\235\264\355\224\204\353\235\274\354\235\270.png" "b/readme-image/\355\214\214\354\235\264\355\224\204\353\235\274\354\235\270.png"
new file mode 100644
index 00000000..b18d2356
Binary files /dev/null and "b/readme-image/\355\214\214\354\235\264\355\224\204\353\235\274\354\235\270.png" differ
diff --git "a/readme-image/\355\230\221\354\227\205.png" "b/readme-image/\355\230\221\354\227\205.png"
new file mode 100644
index 00000000..37d8cc3c
Binary files /dev/null and "b/readme-image/\355\230\221\354\227\205.png" differ
diff --git a/src/main/java/com/moabam/api/application/coupon/CouponCacheService.java b/src/main/java/com/moabam/api/application/coupon/CouponCacheService.java
new file mode 100644
index 00000000..0880a42e
--- /dev/null
+++ b/src/main/java/com/moabam/api/application/coupon/CouponCacheService.java
@@ -0,0 +1,34 @@
+package com.moabam.api.application.coupon;
+
+import java.time.LocalDate;
+import java.util.Optional;
+
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+
+import com.moabam.api.domain.coupon.Coupon;
+import com.moabam.api.domain.coupon.repository.CouponRepository;
+import com.moabam.global.error.exception.NotFoundException;
+import com.moabam.global.error.model.ErrorMessage;
+
+import lombok.RequiredArgsConstructor;
+
+@Service
+@RequiredArgsConstructor
+@CacheConfig(cacheNames = "coupons")
+public class CouponCacheService {
+
+ private final CouponRepository couponRepository;
+
+ @Cacheable(key = "#couponName + #now")
+ public Coupon getByNameAndStartAt(String couponName, LocalDate now) {
+ return couponRepository.findByNameAndStartAt(couponName, now)
+ .orElseThrow(() -> new NotFoundException(ErrorMessage.INVALID_COUPON_PERIOD));
+ }
+
+ @Cacheable(key = "#now")
+ public Optional getByStartAt(LocalDate now) {
+ return couponRepository.findByStartAt(now);
+ }
+}
diff --git a/src/main/java/com/moabam/api/application/coupon/CouponManageService.java b/src/main/java/com/moabam/api/application/coupon/CouponManageService.java
index 3cda6f9a..cadf613c 100644
--- a/src/main/java/com/moabam/api/application/coupon/CouponManageService.java
+++ b/src/main/java/com/moabam/api/application/coupon/CouponManageService.java
@@ -11,12 +11,10 @@
import com.moabam.api.domain.coupon.Coupon;
import com.moabam.api.domain.coupon.CouponWallet;
import com.moabam.api.domain.coupon.repository.CouponManageRepository;
-import com.moabam.api.domain.coupon.repository.CouponRepository;
import com.moabam.api.domain.coupon.repository.CouponWalletRepository;
import com.moabam.global.common.util.ClockHolder;
import com.moabam.global.error.exception.BadRequestException;
import com.moabam.global.error.exception.ConflictException;
-import com.moabam.global.error.exception.NotFoundException;
import com.moabam.global.error.model.ErrorMessage;
import lombok.RequiredArgsConstructor;
@@ -34,14 +32,14 @@ public class CouponManageService {
private final ClockHolder clockHolder;
private final NotificationService notificationService;
- private final CouponRepository couponRepository;
+ private final CouponCacheService couponCacheService;
private final CouponManageRepository couponManageRepository;
private final CouponWalletRepository couponWalletRepository;
@Scheduled(fixedDelay = 1000)
public void issue() {
LocalDate now = clockHolder.date();
- Optional optionalCoupon = couponRepository.findByStartAt(now);
+ Optional optionalCoupon = couponCacheService.getByStartAt(now);
if (optionalCoupon.isEmpty()) {
return;
@@ -70,21 +68,20 @@ public void issue() {
couponManageRepository.increase(couponName, membersId.size());
}
+ public void delete(String couponName) {
+ couponManageRepository.deleteQueue(couponName);
+ couponManageRepository.deleteCount(couponName);
+ }
+
public void registerQueue(String couponName, Long memberId) {
double registerTime = System.currentTimeMillis();
validateRegisterQueue(couponName, memberId);
couponManageRepository.addIfAbsentQueue(couponName, memberId, registerTime);
}
- public void delete(String couponName) {
- couponManageRepository.deleteQueue(couponName);
- couponManageRepository.deleteCount(couponName);
- }
-
private void validateRegisterQueue(String couponName, Long memberId) {
LocalDate now = clockHolder.date();
- Coupon coupon = couponRepository.findByNameAndStartAt(couponName, now)
- .orElseThrow(() -> new NotFoundException(ErrorMessage.INVALID_COUPON_PERIOD));
+ Coupon coupon = couponCacheService.getByNameAndStartAt(couponName, now);
if (couponManageRepository.hasValue(couponName, memberId)) {
throw new ConflictException(ErrorMessage.CONFLICT_COUPON_ISSUE);
diff --git a/src/main/java/com/moabam/api/application/member/MemberService.java b/src/main/java/com/moabam/api/application/member/MemberService.java
index ef3a761c..7c900af5 100644
--- a/src/main/java/com/moabam/api/application/member/MemberService.java
+++ b/src/main/java/com/moabam/api/application/member/MemberService.java
@@ -89,7 +89,7 @@ public void delete(Member member) {
throw new BadRequestException(NEED_TO_EXIT_ALL_ROOMS);
}
- member.delete(clockHolder.times());
+ member.delete(clockHolder.dateTime());
memberRepository.flush();
memberRepository.delete(member);
rankingService.removeRanking(MemberMapper.toRankingInfo(member));
diff --git a/src/main/java/com/moabam/api/application/notification/NotificationService.java b/src/main/java/com/moabam/api/application/notification/NotificationService.java
index 3d8c859b..ab5ef937 100644
--- a/src/main/java/com/moabam/api/application/notification/NotificationService.java
+++ b/src/main/java/com/moabam/api/application/notification/NotificationService.java
@@ -64,7 +64,7 @@ public void sendCouponIssueResult(Long memberId, String couponName, String body)
@Scheduled(cron = "0 55 * * * *")
public void sendCertificationTime() {
- int certificationTime = (clockHolder.times().getHour() + ONE_HOUR) % HOURS_IN_A_DAY;
+ int certificationTime = (clockHolder.dateTime().getHour() + ONE_HOUR) % HOURS_IN_A_DAY;
List participants = participantSearchRepository.findAllByRoomCertifyTime(certificationTime);
participants.parallelStream().forEach(participant -> {
diff --git a/src/main/java/com/moabam/api/application/room/CertificationService.java b/src/main/java/com/moabam/api/application/room/CertificationService.java
index c4e86434..d65f0081 100644
--- a/src/main/java/com/moabam/api/application/room/CertificationService.java
+++ b/src/main/java/com/moabam/api/application/room/CertificationService.java
@@ -70,7 +70,7 @@ public CertifiedMemberInfo getCertifiedMemberInfo(Long memberId, Long roomId, Li
case NIGHT -> BugType.NIGHT;
};
- validateCertifyTime(clockHolder.times(), room.getCertifyTime());
+ validateCertifyTime(clockHolder.dateTime(), room.getCertifyTime());
validateAlreadyCertified(memberId, roomId, today);
certifyMember(memberId, roomId, participant, member, imageUrls);
diff --git a/src/main/java/com/moabam/api/application/room/RoomService.java b/src/main/java/com/moabam/api/application/room/RoomService.java
index 1f2ccdce..e274a560 100644
--- a/src/main/java/com/moabam/api/application/room/RoomService.java
+++ b/src/main/java/com/moabam/api/application/room/RoomService.java
@@ -216,7 +216,7 @@ private void validateEnteredRoomCount(Long memberId, RoomType roomType) {
}
private void validateCertifyTime(Room room) {
- LocalDateTime now = clockHolder.times();
+ LocalDateTime now = clockHolder.dateTime();
LocalTime targetTime = LocalTime.of(room.getCertifyTime(), 0);
LocalDateTime targetDateTime = LocalDateTime.of(now.toLocalDate(), targetTime);
diff --git a/src/main/java/com/moabam/api/application/room/SearchService.java b/src/main/java/com/moabam/api/application/room/SearchService.java
index 91ec3410..1e60f0e8 100644
--- a/src/main/java/com/moabam/api/application/room/SearchService.java
+++ b/src/main/java/com/moabam/api/application/room/SearchService.java
@@ -384,7 +384,7 @@ private double calculateCompletePercentage(int certifiedMembersCount, Room room,
return 0;
}
- LocalDateTime now = clockHolder.times();
+ LocalDateTime now = clockHolder.dateTime();
LocalTime targetTime = LocalTime.of(room.getCertifyTime(), 0);
LocalDateTime targetDateTime = LocalDateTime.of(now.toLocalDate(), targetTime);
diff --git a/src/main/java/com/moabam/api/domain/coupon/repository/CouponRepository.java b/src/main/java/com/moabam/api/domain/coupon/repository/CouponRepository.java
index f236858d..a4ed3c5f 100644
--- a/src/main/java/com/moabam/api/domain/coupon/repository/CouponRepository.java
+++ b/src/main/java/com/moabam/api/domain/coupon/repository/CouponRepository.java
@@ -16,6 +16,4 @@ public interface CouponRepository extends JpaRepository {
Optional findByStartAt(LocalDate startAt);
Optional findByNameAndStartAt(String couponName, LocalDate startAt);
-
- boolean existsByNameAndStartAt(String couponName, LocalDate startAt);
}
diff --git a/src/main/java/com/moabam/global/common/util/ClockHolder.java b/src/main/java/com/moabam/global/common/util/ClockHolder.java
index 1ba7a0c5..4afc579b 100644
--- a/src/main/java/com/moabam/global/common/util/ClockHolder.java
+++ b/src/main/java/com/moabam/global/common/util/ClockHolder.java
@@ -2,10 +2,15 @@
import java.time.LocalDate;
import java.time.LocalDateTime;
+import java.time.LocalTime;
public interface ClockHolder {
- LocalDateTime times();
+ LocalDateTime dateTime();
LocalDate date();
+
+ LocalTime time();
+
+ LocalTime endOfDay();
}
diff --git a/src/main/java/com/moabam/global/common/util/SystemClockHolder.java b/src/main/java/com/moabam/global/common/util/SystemClockHolder.java
index 8804769c..756457bc 100644
--- a/src/main/java/com/moabam/global/common/util/SystemClockHolder.java
+++ b/src/main/java/com/moabam/global/common/util/SystemClockHolder.java
@@ -2,6 +2,7 @@
import java.time.LocalDate;
import java.time.LocalDateTime;
+import java.time.LocalTime;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
@@ -11,7 +12,7 @@
public class SystemClockHolder implements ClockHolder {
@Override
- public LocalDateTime times() {
+ public LocalDateTime dateTime() {
return LocalDateTime.now();
}
@@ -19,4 +20,14 @@ public LocalDateTime times() {
public LocalDate date() {
return LocalDate.now();
}
+
+ @Override
+ public LocalTime time() {
+ return LocalTime.now();
+ }
+
+ @Override
+ public LocalTime endOfDay() {
+ return LocalTime.of(23, 59, 59, 999_999_999);
+ }
}
diff --git a/src/main/java/com/moabam/global/config/CacheConfig.java b/src/main/java/com/moabam/global/config/CacheConfig.java
new file mode 100644
index 00000000..974f1bf3
--- /dev/null
+++ b/src/main/java/com/moabam/global/config/CacheConfig.java
@@ -0,0 +1,62 @@
+package com.moabam.global.config;
+
+import static org.springframework.data.redis.serializer.RedisSerializationContext.*;
+
+import java.time.Duration;
+import java.time.LocalTime;
+
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
+import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.moabam.global.common.util.ClockHolder;
+
+import lombok.RequiredArgsConstructor;
+
+@EnableCaching
+@Configuration
+@RequiredArgsConstructor
+public class CacheConfig {
+
+ private final ClockHolder clockHolder;
+
+ @Bean
+ public RedisCacheConfiguration redisCacheConfiguration() {
+ var strSerializePair = SerializationPair.fromSerializer(new StringRedisSerializer());
+ var objSerializePair = SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer(objectMapper()));
+
+ return RedisCacheConfiguration.defaultCacheConfig()
+ .entryTtl(getTtl())
+ .serializeKeysWith(strSerializePair)
+ .serializeValuesWith(objSerializePair);
+ }
+
+ private Duration getTtl() {
+ LocalTime now = clockHolder.time();
+ LocalTime end = clockHolder.endOfDay();
+
+ return Duration.between(now, end);
+ }
+
+ private ObjectMapper objectMapper() {
+ PolymorphicTypeValidator polymorphicTypeValidator = BasicPolymorphicTypeValidator.builder()
+ .allowIfSubType(Object.class)
+ .build();
+
+ return JsonMapper.builder()
+ .polymorphicTypeValidator(polymorphicTypeValidator)
+ .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
+ .addModule(new JavaTimeModule())
+ .activateDefaultTyping(polymorphicTypeValidator, ObjectMapper.DefaultTyping.NON_FINAL)
+ .build();
+ }
+}
diff --git a/src/test/java/com/moabam/api/application/coupon/CouponManageServiceTest.java b/src/test/java/com/moabam/api/application/coupon/CouponManageServiceTest.java
index d209cdfe..881842b1 100644
--- a/src/test/java/com/moabam/api/application/coupon/CouponManageServiceTest.java
+++ b/src/test/java/com/moabam/api/application/coupon/CouponManageServiceTest.java
@@ -21,11 +21,9 @@
import com.moabam.api.domain.coupon.Coupon;
import com.moabam.api.domain.coupon.CouponWallet;
import com.moabam.api.domain.coupon.repository.CouponManageRepository;
-import com.moabam.api.domain.coupon.repository.CouponRepository;
import com.moabam.api.domain.coupon.repository.CouponWalletRepository;
import com.moabam.global.common.util.ClockHolder;
import com.moabam.global.error.exception.NotFoundException;
-import com.moabam.global.error.model.ErrorMessage;
import com.moabam.support.common.FilterProcessExtension;
import com.moabam.support.fixture.CouponFixture;
@@ -39,7 +37,7 @@ class CouponManageServiceTest {
NotificationService notificationService;
@Mock
- CouponRepository couponRepository;
+ CouponCacheService couponCacheService;
@Mock
CouponManageRepository couponManageRepository;
@@ -58,7 +56,7 @@ void issue_all_success(Set values) {
Coupon coupon = CouponFixture.coupon(1000, 100);
given(clockHolder.date()).willReturn(LocalDate.now());
- given(couponRepository.findByStartAt(any(LocalDate.class))).willReturn(Optional.of(coupon));
+ given(couponCacheService.getByStartAt(any(LocalDate.class))).willReturn(Optional.of(coupon));
given(couponManageRepository.rangeQueue(any(String.class), any(long.class), any(long.class)))
.willReturn(values);
given(couponManageRepository.getCount(any(String.class))).willReturn(coupon.getMaxCount() - 1);
@@ -77,7 +75,7 @@ void issue_all_success(Set values) {
void issue_notStartAt() {
// Given
given(clockHolder.date()).willReturn(LocalDate.now());
- given(couponRepository.findByStartAt(any(LocalDate.class))).willReturn(Optional.empty());
+ given(couponCacheService.getByStartAt(any(LocalDate.class))).willReturn(Optional.empty());
// When
couponManageService.issue();
@@ -98,7 +96,7 @@ void issue_stockEnd() {
Coupon coupon = CouponFixture.coupon(1000, 100);
given(clockHolder.date()).willReturn(LocalDate.now());
- given(couponRepository.findByStartAt(any(LocalDate.class))).willReturn(Optional.of(coupon));
+ given(couponCacheService.getByStartAt(any(LocalDate.class))).willReturn(Optional.of(coupon));
given(couponManageRepository.getCount(any(String.class))).willReturn(coupon.getMaxCount());
// When
@@ -120,8 +118,7 @@ void registerQueue_success() {
given(clockHolder.date()).willReturn(LocalDate.now());
given(couponManageRepository.sizeQueue(any(String.class))).willReturn(coupon.getMaxCount() - 1);
- given(couponRepository.findByNameAndStartAt(any(String.class), any(LocalDate.class)))
- .willReturn(Optional.of(coupon));
+ given(couponCacheService.getByNameAndStartAt(any(String.class), any(LocalDate.class))).willReturn(coupon);
// When
couponManageService.registerQueue(coupon.getName(), 1L);
@@ -135,13 +132,12 @@ void registerQueue_success() {
void registerQueue_No_BadRequestException() {
// Given
given(clockHolder.date()).willReturn(LocalDate.now());
- given(couponRepository.findByNameAndStartAt(any(String.class), any(LocalDate.class)))
- .willReturn(Optional.empty());
+ given(couponCacheService.getByNameAndStartAt(any(String.class), any(LocalDate.class)))
+ .willThrow(NotFoundException.class);
// When & Then
assertThatThrownBy(() -> couponManageService.registerQueue("couponName", 1L))
- .isInstanceOf(NotFoundException.class)
- .hasMessage(ErrorMessage.INVALID_COUPON_PERIOD.getMessage());
+ .isInstanceOf(NotFoundException.class);
}
@DisplayName("์ฟ ํฐ ๋๊ธฐ์ด๊ณผ ๋ฐํ๋ ์ฌ๊ณ ๊ฐ ์ ์์ ์ผ๋ก ์ญ์ ๋๋ค.")
diff --git a/src/test/java/com/moabam/api/application/member/MemberServiceTest.java b/src/test/java/com/moabam/api/application/member/MemberServiceTest.java
index 5bb68977..dc28bb72 100644
--- a/src/test/java/com/moabam/api/application/member/MemberServiceTest.java
+++ b/src/test/java/com/moabam/api/application/member/MemberServiceTest.java
@@ -129,7 +129,7 @@ void signUp_success() {
void undo_delete_member(@WithMember AuthMember authMember) {
// given
Member member = MemberFixture.member();
- given(clockHolder.times()).willReturn(LocalDateTime.now());
+ given(clockHolder.dateTime()).willReturn(LocalDateTime.now());
// When
memberService.delete(member);
diff --git a/src/test/java/com/moabam/api/application/notification/NotificationServiceTest.java b/src/test/java/com/moabam/api/application/notification/NotificationServiceTest.java
index a08d2b06..2cb980ee 100644
--- a/src/test/java/com/moabam/api/application/notification/NotificationServiceTest.java
+++ b/src/test/java/com/moabam/api/application/notification/NotificationServiceTest.java
@@ -169,7 +169,7 @@ void sendCertificationTime_success(List participants) {
// Given
given(participantSearchRepository.findAllByRoomCertifyTime(any(Integer.class))).willReturn(participants);
given(fcmService.findTokenByMemberId(any(Long.class))).willReturn(Optional.of("FCM-TOKEN"));
- given(clockHolder.times()).willReturn(LocalDateTime.now());
+ given(clockHolder.dateTime()).willReturn(LocalDateTime.now());
// When
notificationService.sendCertificationTime();
@@ -186,7 +186,7 @@ void sendCertificationTime_NoFirebaseMessaging(List participants) {
// Given
given(participantSearchRepository.findAllByRoomCertifyTime(any(Integer.class))).willReturn(participants);
given(fcmService.findTokenByMemberId(any(Long.class))).willReturn(Optional.empty());
- given(clockHolder.times()).willReturn(LocalDateTime.now());
+ given(clockHolder.dateTime()).willReturn(LocalDateTime.now());
// When
notificationService.sendCertificationTime();
diff --git a/src/test/java/com/moabam/api/application/room/CertificationServiceTest.java b/src/test/java/com/moabam/api/application/room/CertificationServiceTest.java
index e02eac44..ad8b6579 100644
--- a/src/test/java/com/moabam/api/application/room/CertificationServiceTest.java
+++ b/src/test/java/com/moabam/api/application/room/CertificationServiceTest.java
@@ -131,7 +131,7 @@ void get_certified_member_info_success() {
imageUrls.add("https://image.moabam.com/certifications/20231108/1_asdfsdfxcv-4815vcx-asfd");
imageUrls.add("https://image.moabam.com/certifications/20231108/2_asdfsdfxcv-4815vcx-asfd");
- given(clockHolder.times()).willReturn(LocalDateTime.now().withHour(10).withMinute(6));
+ given(clockHolder.dateTime()).willReturn(LocalDateTime.now().withHour(10).withMinute(6));
given(clockHolder.date()).willReturn(today);
given(participantSearchRepository.findOne(memberId, roomId)).willReturn(Optional.of(participant));
given(memberService.findMember(memberId)).willReturn(member1);
diff --git a/src/test/java/com/moabam/api/presentation/CouponControllerTest.java b/src/test/java/com/moabam/api/presentation/CouponControllerTest.java
index 65f25723..3f85f40c 100644
--- a/src/test/java/com/moabam/api/presentation/CouponControllerTest.java
+++ b/src/test/java/com/moabam/api/presentation/CouponControllerTest.java
@@ -20,6 +20,7 @@
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.transaction.annotation.Transactional;
@@ -68,7 +69,7 @@ class CouponControllerTest extends WithoutFilterSupporter {
@Autowired
CouponWalletRepository couponWalletRepository;
- @MockBean
+ @SpyBean
ClockHolder clockHolder;
@MockBean
diff --git a/src/test/java/com/moabam/support/common/TestClockHolder.java b/src/test/java/com/moabam/support/common/TestClockHolder.java
index aa75977d..3b21a0cd 100644
--- a/src/test/java/com/moabam/support/common/TestClockHolder.java
+++ b/src/test/java/com/moabam/support/common/TestClockHolder.java
@@ -2,6 +2,7 @@
import java.time.LocalDate;
import java.time.LocalDateTime;
+import java.time.LocalTime;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
@@ -13,7 +14,7 @@
public class TestClockHolder implements ClockHolder {
@Override
- public LocalDateTime times() {
+ public LocalDateTime dateTime() {
return LocalDateTime.of(2023, 12, 3, 14, 30, 0);
}
@@ -21,4 +22,14 @@ public LocalDateTime times() {
public LocalDate date() {
return LocalDateTime.now().toLocalDate();
}
+
+ @Override
+ public LocalTime time() {
+ return LocalTime.of(23, 50, 50);
+ }
+
+ @Override
+ public LocalTime endOfDay() {
+ return LocalTime.of(23, 59, 59, 999_999_999);
+ }
}