From 84141c8fecba045fe65b385debd07a77ab15fc33 Mon Sep 17 00:00:00 2001 From: handwoong Date: Mon, 29 Dec 2025 07:19:08 +0900 Subject: [PATCH 1/6] =?UTF-8?q?chore:=20=EB=B9=8C=EB=93=9C=20=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A6=BD=ED=8A=B8=20IDE=20=EA=B2=BD=EA=B3=A0=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 44 ++++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 20f7d7d3..0e1b59ca 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -18,32 +18,7 @@ java { } } -configurations { - compileOnly { - extendsFrom(configurations.annotationProcessor.get()) - } - - configureEach { - exclude(group = "commons-logging", module = "commons-logging") - } -} - -repositories { - mavenCentral() -} - -springBoot { - buildInfo() -} - val springCloud: String by project - -dependencyManagement { - imports { - mavenBom("org.springframework.cloud:spring-cloud-dependencies:$springCloud") - } -} - val jjwt: String by project val mockito: String by project val oci: String by project @@ -54,8 +29,17 @@ val redisson: String by project val scrimage: String by project val springdoc: String by project val tsid: String by project +val mockitoAgent: Configuration? = configurations.create("mockitoAgent") + +repositories { + mavenCentral() +} -val mockitoAgent = configurations.create("mockitoAgent") +dependencyManagement { + imports { + mavenBom("org.springframework.cloud:spring-cloud-dependencies:$springCloud") + } +} dependencies { implementation("org.springframework.boot:spring-boot-starter-actuator") @@ -103,7 +87,7 @@ dependencies { testImplementation("org.junit-pioneer:junit-pioneer:$pioneer") testImplementation("org.testcontainers:mysql") testImplementation("org.mockito:mockito-core:$mockito") - mockitoAgent("org.mockito:mockito-core:$mockito") { isTransitive = false } + mockitoAgent?.let { it("org.mockito:mockito-core:$mockito") { isTransitive = false } } testCompileOnly("org.projectlombok:lombok") testAnnotationProcessor("org.projectlombok:lombok") @@ -112,9 +96,13 @@ dependencies { tasks.withType { useJUnitPlatform() - jvmArgs("-javaagent:${mockitoAgent.asPath}", "-Xshare:off") + mockitoAgent?.let { jvmArgs("-javaagent:${it.asPath}", "-Xshare:off") } } spotbugs { excludeFilter.set(file("${projectDir}/spotbugs-exclude.xml")) } + +springBoot { + buildInfo() +} From 35383391b7d58e65c8bd6eb95e9381a7c4298b5a Mon Sep 17 00:00:00 2001 From: handwoong Date: Mon, 29 Dec 2025 08:52:40 +0900 Subject: [PATCH 2/6] =?UTF-8?q?chore:=20=EC=8A=A4=ED=94=84=EB=A7=81=20?= =?UTF-8?q?=EB=B6=80=ED=8A=B8=204.0=20=EB=A7=88=EC=9D=B4=EA=B7=B8=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 25 +- gradle.properties | 26 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../integration/CacheConfiguration.java | 7 +- .../persistence/RedisConfiguration.java | 5 +- .../adapter/persistence/RedisProperties.java | 16 ++ .../security/SecurityConfiguration.java | 2 +- .../web/config/InstantJsonSerializer.java | 4 +- .../adapter/web/config/MDCLoggingFilter.java | 10 +- .../config/MultipartHttpMessageConverter.java | 37 +++ ...MultipartJackson2HttpMessageConverter.java | 32 --- .../application/sse/SseService.java | 9 +- .../java/com/everyonewaiter/package-info.java | 6 +- .../DatabaseCleanUpExtension.java | 17 -- .../com/everyonewaiter/DatabaseCleaner.java | 45 ---- .../EveryonewaiterApiApplicationTest.java | 19 -- .../ExternalSystemTestConfiguration.java | 48 ---- .../com/everyonewaiter/IntegrationTest.java | 14 -- .../everyonewaiter/TestContainerCreator.java | 36 --- .../everyonewaiter/TestContainerSupport.java | 41 --- .../provided/AccountCreateEventListener.java | 28 --- .../account/provided/AccountFinderTest.java | 95 ------- .../account/provided/AccountRegisterTest.java | 98 -------- .../provided/AccountSignInHandlerTest.java | 107 -------- .../account/provided/AccountUpdaterTest.java | 88 ------- .../provided/AccountValidatorTest.java | 96 ------- .../required/AccountRepositoryTest.java | 207 --------------- .../provided/AuthCodeSendEventListener.java | 28 --- .../provided/AuthMailSendEventListener.java | 28 --- .../auth/provided/AuthenticatorTest.java | 238 ------------------ .../provided/SignInTokenProviderTest.java | 93 ------- .../auth/required/AuthRepositoryTest.java | 73 ------ .../auth/required/JwtProviderTest.java | 29 --- .../required/RefreshTokenRepositoryTest.java | 50 ---- .../auth/required/SignatureEncoderTest.java | 21 -- .../provided/HealthCheckCreatorTest.java | 42 ---- .../provided/HealthCheckFinderTest.java | 38 --- .../required/ApkVersionRepositoryTest.java | 35 --- .../provided/NotificationSenderTest.java | 56 ----- .../required/AlimTalkSenderTest.java | 29 --- .../required/DiscordWebhookSenderTest.java | 28 --- .../required/EmailSenderTest.java | 28 --- 42 files changed, 103 insertions(+), 1833 deletions(-) create mode 100644 src/main/java/com/everyonewaiter/adapter/persistence/RedisProperties.java create mode 100644 src/main/java/com/everyonewaiter/adapter/web/config/MultipartHttpMessageConverter.java delete mode 100644 src/main/java/com/everyonewaiter/adapter/web/config/MultipartJackson2HttpMessageConverter.java delete mode 100644 src/test/java/com/everyonewaiter/DatabaseCleanUpExtension.java delete mode 100644 src/test/java/com/everyonewaiter/DatabaseCleaner.java delete mode 100644 src/test/java/com/everyonewaiter/EveryonewaiterApiApplicationTest.java delete mode 100644 src/test/java/com/everyonewaiter/ExternalSystemTestConfiguration.java delete mode 100644 src/test/java/com/everyonewaiter/IntegrationTest.java delete mode 100644 src/test/java/com/everyonewaiter/TestContainerCreator.java delete mode 100644 src/test/java/com/everyonewaiter/TestContainerSupport.java delete mode 100644 src/test/java/com/everyonewaiter/application/account/provided/AccountCreateEventListener.java delete mode 100644 src/test/java/com/everyonewaiter/application/account/provided/AccountFinderTest.java delete mode 100644 src/test/java/com/everyonewaiter/application/account/provided/AccountRegisterTest.java delete mode 100644 src/test/java/com/everyonewaiter/application/account/provided/AccountSignInHandlerTest.java delete mode 100644 src/test/java/com/everyonewaiter/application/account/provided/AccountUpdaterTest.java delete mode 100644 src/test/java/com/everyonewaiter/application/account/provided/AccountValidatorTest.java delete mode 100644 src/test/java/com/everyonewaiter/application/account/required/AccountRepositoryTest.java delete mode 100644 src/test/java/com/everyonewaiter/application/auth/provided/AuthCodeSendEventListener.java delete mode 100644 src/test/java/com/everyonewaiter/application/auth/provided/AuthMailSendEventListener.java delete mode 100644 src/test/java/com/everyonewaiter/application/auth/provided/AuthenticatorTest.java delete mode 100644 src/test/java/com/everyonewaiter/application/auth/provided/SignInTokenProviderTest.java delete mode 100644 src/test/java/com/everyonewaiter/application/auth/required/AuthRepositoryTest.java delete mode 100644 src/test/java/com/everyonewaiter/application/auth/required/JwtProviderTest.java delete mode 100644 src/test/java/com/everyonewaiter/application/auth/required/RefreshTokenRepositoryTest.java delete mode 100644 src/test/java/com/everyonewaiter/application/auth/required/SignatureEncoderTest.java delete mode 100644 src/test/java/com/everyonewaiter/application/health/provided/HealthCheckCreatorTest.java delete mode 100644 src/test/java/com/everyonewaiter/application/health/provided/HealthCheckFinderTest.java delete mode 100644 src/test/java/com/everyonewaiter/application/health/required/ApkVersionRepositoryTest.java delete mode 100644 src/test/java/com/everyonewaiter/application/notification/provided/NotificationSenderTest.java delete mode 100644 src/test/java/com/everyonewaiter/application/notification/required/AlimTalkSenderTest.java delete mode 100644 src/test/java/com/everyonewaiter/application/notification/required/DiscordWebhookSenderTest.java delete mode 100644 src/test/java/com/everyonewaiter/application/notification/required/EmailSenderTest.java diff --git a/build.gradle.kts b/build.gradle.kts index 0e1b59ca..dcc59e4f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,9 +8,11 @@ plugins { val appGroup: String by project val appVersion: String by project +val appDescription: String by project group = appGroup version = appVersion +description = appDescription java { toolchain { @@ -22,7 +24,6 @@ val springCloud: String by project val jjwt: String by project val mockito: String by project val oci: String by project -val pioneer: String by project val queryDSL: String by project val pdfbox: String by project val redisson: String by project @@ -43,15 +44,17 @@ dependencyManagement { dependencies { implementation("org.springframework.boot:spring-boot-starter-actuator") - implementation("org.springframework.boot:spring-boot-starter-aop") + implementation("org.springframework.boot:spring-boot-starter-aspectj") implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.springframework.boot:spring-boot-starter-data-redis") + implementation("org.springframework.boot:spring-boot-starter-flyway") implementation("org.springframework.boot:spring-boot-starter-mail") implementation("org.springframework.boot:spring-boot-starter-security") implementation("org.springframework.boot:spring-boot-starter-thymeleaf") implementation("org.springframework.boot:spring-boot-starter-validation") - implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-webmvc") implementation("org.springframework.cloud:spring-cloud-starter-openfeign") + implementation("org.flywaydb:flyway-mysql") implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:$springdoc") { exclude(group = "org.webjars", module = "swagger-ui") } @@ -66,8 +69,6 @@ dependencies { implementation("com.oracle.oci.sdk:oci-java-sdk-common:$oci") implementation("com.oracle.oci.sdk:oci-java-sdk-objectstorage:$oci") implementation("com.oracle.oci.sdk:oci-java-sdk-common-httpclient-jersey3:$oci") - implementation("org.flywaydb:flyway-core") - implementation("org.flywaydb:flyway-mysql") compileOnly("org.projectlombok:lombok") @@ -81,11 +82,15 @@ dependencies { annotationProcessor("jakarta.annotation:jakarta.annotation-api") annotationProcessor("jakarta.persistence:jakarta.persistence-api") - testImplementation("org.springframework.boot:spring-boot-starter-test") - testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.junit-pioneer:junit-pioneer:$pioneer") - testImplementation("org.testcontainers:mysql") + testImplementation("org.springframework.boot:spring-boot-starter-actuator-test") + testImplementation("org.springframework.boot:spring-boot-starter-data-jpa-test") + testImplementation("org.springframework.boot:spring-boot-starter-data-redis-test") + testImplementation("org.springframework.boot:spring-boot-starter-flyway-test") + testImplementation("org.springframework.boot:spring-boot-starter-mail-test") + testImplementation("org.springframework.boot:spring-boot-starter-security-test") + testImplementation("org.springframework.boot:spring-boot-starter-thymeleaf-test") + testImplementation("org.springframework.boot:spring-boot-starter-validation-test") + testImplementation("org.springframework.boot:spring-boot-starter-webmvc-test") testImplementation("org.mockito:mockito-core:$mockito") mockitoAgent?.let { it("org.mockito:mockito-core:$mockito") { isTransitive = false } } diff --git a/gradle.properties b/gradle.properties index f401b10c..1df2bfa5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,22 +1,22 @@ # Artifact appGroup=com.everyonewaiter appVersion=1.0.7 +appDescription=모두의 웨이터 API # Plugin -springBoot=3.5.4 -springCloud=2025.0.0 +springBoot=4.0.1 +springCloud=2025.1.0 springDependencyManagement=1.1.7 -gitProperties=2.5.2 -spotBugs=6.2.4 +gitProperties=2.5.4 +spotBugs=6.4.8 # Dependencies -jjwt=0.12.6 -mockito=5.18.0 -oci=3.70.0 -pioneer=2.3.0 -queryDSL=7.0 -pdfbox=3.0.5 -redisson=3.50.0 -scrimage=4.3.3 -springdoc=2.8.9 +jjwt=0.13.0 +mockito=5.21.0 +oci=3.77.2 +queryDSL=7.1 +pdfbox=3.0.6 +redisson=4.0.0 +scrimage=4.3.5 +springdoc=3.0.0 tsid=5.2.6 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 37f853b1..23449a2b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/com/everyonewaiter/adapter/integration/CacheConfiguration.java b/src/main/java/com/everyonewaiter/adapter/integration/CacheConfiguration.java index fa8f5253..cd1356dd 100644 --- a/src/main/java/com/everyonewaiter/adapter/integration/CacheConfiguration.java +++ b/src/main/java/com/everyonewaiter/adapter/integration/CacheConfiguration.java @@ -8,9 +8,10 @@ import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; -import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.GenericJacksonJsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.StringRedisSerializer; +import tools.jackson.databind.json.JsonMapper; @Configuration @EnableCaching @@ -28,7 +29,7 @@ public CacheManager cacheManager( } @Bean - public RedisCacheConfiguration redisCacheConfiguration() { + public RedisCacheConfiguration redisCacheConfiguration(JsonMapper jsonMapper) { return RedisCacheConfiguration.defaultCacheConfig() .disableCachingNullValues() .serializeKeysWith( @@ -37,7 +38,7 @@ public RedisCacheConfiguration redisCacheConfiguration() { ) .serializeValuesWith( RedisSerializationContext.SerializationPair - .fromSerializer(new GenericJackson2JsonRedisSerializer()) + .fromSerializer(new GenericJacksonJsonRedisSerializer(jsonMapper)) ) .entryTtl(Duration.ofHours(3)); } diff --git a/src/main/java/com/everyonewaiter/adapter/persistence/RedisConfiguration.java b/src/main/java/com/everyonewaiter/adapter/persistence/RedisConfiguration.java index 7185e248..f5532f21 100644 --- a/src/main/java/com/everyonewaiter/adapter/persistence/RedisConfiguration.java +++ b/src/main/java/com/everyonewaiter/adapter/persistence/RedisConfiguration.java @@ -4,7 +4,6 @@ import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; -import org.springframework.boot.autoconfigure.data.redis.RedisProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; @@ -46,8 +45,8 @@ public RedissonClient redissonClient() { + redisProperties.getHost() + ":" + redisProperties.getPort() - ) - .setPassword(redisProperties.getPassword()); + ); + config.setPassword(redisProperties.getPassword()); return Redisson.create(config); } diff --git a/src/main/java/com/everyonewaiter/adapter/persistence/RedisProperties.java b/src/main/java/com/everyonewaiter/adapter/persistence/RedisProperties.java new file mode 100644 index 00000000..71e293a5 --- /dev/null +++ b/src/main/java/com/everyonewaiter/adapter/persistence/RedisProperties.java @@ -0,0 +1,16 @@ +package com.everyonewaiter.adapter.persistence; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Getter +@ConfigurationProperties(prefix = "spring.data.redis") +@RequiredArgsConstructor +class RedisProperties { + + private final String host; + private final int port; + private final String password; + +} diff --git a/src/main/java/com/everyonewaiter/adapter/security/SecurityConfiguration.java b/src/main/java/com/everyonewaiter/adapter/security/SecurityConfiguration.java index 61f049e0..ea7fffc0 100644 --- a/src/main/java/com/everyonewaiter/adapter/security/SecurityConfiguration.java +++ b/src/main/java/com/everyonewaiter/adapter/security/SecurityConfiguration.java @@ -35,7 +35,7 @@ public CorsConfigurationSource corsConfigurationSource() { } @Bean - public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + public SecurityFilterChain securityFilterChain(HttpSecurity http) { return http.cors(cors -> cors.configurationSource(corsConfigurationSource())) .csrf(AbstractHttpConfigurer::disable) .formLogin(AbstractHttpConfigurer::disable) diff --git a/src/main/java/com/everyonewaiter/adapter/web/config/InstantJsonSerializer.java b/src/main/java/com/everyonewaiter/adapter/web/config/InstantJsonSerializer.java index 6eeb073d..e2a38c31 100644 --- a/src/main/java/com/everyonewaiter/adapter/web/config/InstantJsonSerializer.java +++ b/src/main/java/com/everyonewaiter/adapter/web/config/InstantJsonSerializer.java @@ -8,9 +8,9 @@ import com.fasterxml.jackson.databind.SerializerProvider; import java.io.IOException; import java.time.Instant; -import org.springframework.boot.jackson.JsonComponent; +import org.springframework.boot.jackson.JacksonComponent; -@JsonComponent +@JacksonComponent class InstantJsonSerializer extends JsonSerializer { @Override diff --git a/src/main/java/com/everyonewaiter/adapter/web/config/MDCLoggingFilter.java b/src/main/java/com/everyonewaiter/adapter/web/config/MDCLoggingFilter.java index 1548d86c..bbda5953 100644 --- a/src/main/java/com/everyonewaiter/adapter/web/config/MDCLoggingFilter.java +++ b/src/main/java/com/everyonewaiter/adapter/web/config/MDCLoggingFilter.java @@ -5,36 +5,36 @@ import static com.everyonewaiter.adapter.web.HttpRequestParser.parseRequestUri; import static com.everyonewaiter.adapter.web.HttpRequestParser.parseXRequestId; -import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import lombok.RequiredArgsConstructor; +import org.jspecify.annotations.NonNull; import org.slf4j.MDC; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; +import tools.jackson.databind.json.JsonMapper; @Component @RequiredArgsConstructor class MDCLoggingFilter extends OncePerRequestFilter { - private final ObjectMapper objectMapper; + private final JsonMapper jsonMapper; @Override protected void doFilterInternal( @NonNull HttpServletRequest request, @NonNull HttpServletResponse response, - @NonNull FilterChain filterChain + FilterChain filterChain ) throws ServletException, IOException { MDC.put("requestId", parseXRequestId(request)); MDC.put("requestMethod", request.getMethod()); MDC.put("requestUri", parseRequestUri(request)); MDC.put("requestParameters", parseParameters(request)); MDC.put("requestHeaders", parseHeaders(request)); - MDC.put("requestCookies", objectMapper.writeValueAsString(request.getCookies())); + MDC.put("requestCookies", jsonMapper.writeValueAsString(request.getCookies())); try { filterChain.doFilter(request, response); diff --git a/src/main/java/com/everyonewaiter/adapter/web/config/MultipartHttpMessageConverter.java b/src/main/java/com/everyonewaiter/adapter/web/config/MultipartHttpMessageConverter.java new file mode 100644 index 00000000..e01b37be --- /dev/null +++ b/src/main/java/com/everyonewaiter/adapter/web/config/MultipartHttpMessageConverter.java @@ -0,0 +1,37 @@ +package com.everyonewaiter.adapter.web.config; + +import lombok.NonNull; +import org.jspecify.annotations.Nullable; +import org.springframework.core.ResolvableType; +import org.springframework.http.MediaType; +import org.springframework.http.converter.AbstractJacksonHttpMessageConverter; +import org.springframework.stereotype.Component; +import tools.jackson.databind.json.JsonMapper; + +@Component +class MultipartHttpMessageConverter extends AbstractJacksonHttpMessageConverter { + + protected MultipartHttpMessageConverter(JsonMapper jsonMapper) { + super(jsonMapper, MediaType.APPLICATION_OCTET_STREAM); + } + + @Override + protected boolean canWrite(MediaType mediaType) { + return false; + } + + @Override + public boolean canWrite(@NonNull Class clazz, MediaType mediaType) { + return false; + } + + @Override + public boolean canWrite( + @NonNull ResolvableType type, + @NonNull Class valueClass, + @Nullable MediaType mediaType + ) { + return false; + } + +} diff --git a/src/main/java/com/everyonewaiter/adapter/web/config/MultipartJackson2HttpMessageConverter.java b/src/main/java/com/everyonewaiter/adapter/web/config/MultipartJackson2HttpMessageConverter.java deleted file mode 100644 index af36128c..00000000 --- a/src/main/java/com/everyonewaiter/adapter/web/config/MultipartJackson2HttpMessageConverter.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.everyonewaiter.adapter.web.config; - -import com.fasterxml.jackson.databind.ObjectMapper; -import java.lang.reflect.Type; -import lombok.NonNull; -import org.springframework.http.MediaType; -import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter; -import org.springframework.stereotype.Component; - -@Component -class MultipartJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter { - - protected MultipartJackson2HttpMessageConverter(ObjectMapper objectMapper) { - super(objectMapper, MediaType.APPLICATION_OCTET_STREAM); - } - - @Override - protected boolean canWrite(MediaType mediaType) { - return false; - } - - @Override - public boolean canWrite(@NonNull Class clazz, MediaType mediaType) { - return false; - } - - @Override - public boolean canWrite(Type type, @NonNull Class clazz, MediaType mediaType) { - return false; - } - -} diff --git a/src/main/java/com/everyonewaiter/application/sse/SseService.java b/src/main/java/com/everyonewaiter/application/sse/SseService.java index ef8245ab..44221cc5 100644 --- a/src/main/java/com/everyonewaiter/application/sse/SseService.java +++ b/src/main/java/com/everyonewaiter/application/sse/SseService.java @@ -9,7 +9,6 @@ import com.everyonewaiter.application.sse.required.SseEmitterRepository; import com.everyonewaiter.application.sse.required.SseEventRepository; import com.everyonewaiter.domain.sse.SseEvent; -import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.time.Duration; import lombok.RequiredArgsConstructor; @@ -17,6 +16,8 @@ import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; +import tools.jackson.core.JacksonException; +import tools.jackson.databind.json.JsonMapper; @Service @RequiredArgsConstructor @@ -26,7 +27,7 @@ class SseService implements SseConnector, SseSender { private static final String CONNECT_EVENT = "CONNECTED!"; - private final ObjectMapper objectMapper; + private final JsonMapper jsonMapper; private final SseEmitterRepository sseEmitterRepository; private final SseEventRepository sseEventRepository; @@ -80,13 +81,13 @@ public void send(String prefix, SseEvent sseEvent) { String eventKey = EVENT.createKey(prefix); try { - String event = objectMapper.writeValueAsString(sseEvent); + String event = jsonMapper.writeValueAsString(sseEvent); sseEventRepository.save(eventKey, event); sseEmitterRepository.findAllByScanKey(EMITTER.createScanKey(prefix)) .values() .forEach(sseEmitter -> send(sseEmitter, eventKey, event)); - } catch (IOException exception) { + } catch (JacksonException exception) { LOGGER.warn("[SSE] Failed to serialize event. eventKey: {}", eventKey); } } diff --git a/src/main/java/com/everyonewaiter/package-info.java b/src/main/java/com/everyonewaiter/package-info.java index 0d52c47d..c7743c9b 100644 --- a/src/main/java/com/everyonewaiter/package-info.java +++ b/src/main/java/com/everyonewaiter/package-info.java @@ -1,6 +1,4 @@ -@NonNullApi -@NonNullFields +@NullMarked package com.everyonewaiter; -import org.springframework.lang.NonNullApi; -import org.springframework.lang.NonNullFields; +import org.jspecify.annotations.NullMarked; diff --git a/src/test/java/com/everyonewaiter/DatabaseCleanUpExtension.java b/src/test/java/com/everyonewaiter/DatabaseCleanUpExtension.java deleted file mode 100644 index 4bc4956f..00000000 --- a/src/test/java/com/everyonewaiter/DatabaseCleanUpExtension.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.everyonewaiter; - -import static org.springframework.test.context.junit.jupiter.SpringExtension.getApplicationContext; - -import org.junit.jupiter.api.extension.AfterEachCallback; -import org.junit.jupiter.api.extension.ExtensionContext; - -class DatabaseCleanUpExtension implements AfterEachCallback { - - @Override - public void afterEach(ExtensionContext context) { - DatabaseCleaner databaseCleaner = getApplicationContext(context).getBean(DatabaseCleaner.class); - - databaseCleaner.clean(); - } - -} diff --git a/src/test/java/com/everyonewaiter/DatabaseCleaner.java b/src/test/java/com/everyonewaiter/DatabaseCleaner.java deleted file mode 100644 index 4877ea66..00000000 --- a/src/test/java/com/everyonewaiter/DatabaseCleaner.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.everyonewaiter; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.stereotype.Component; - -@Component -@RequiredArgsConstructor -class DatabaseCleaner { - - private final JdbcTemplate jdbcTemplate; - private final RedisConnectionFactory redisConnectionFactory; - - public void clean() { - cleanMysql(); - cleanRedis(); - } - - private void cleanMysql() { - jdbcTemplate.execute("SET FOREIGN_KEY_CHECKS = 0"); - - getTruncateQueries().forEach(jdbcTemplate::execute); - - jdbcTemplate.execute("SET FOREIGN_KEY_CHECKS = 1"); - } - - private void cleanRedis() { - try (var connection = redisConnectionFactory.getConnection()) { - connection.serverCommands().flushDb(); - } - } - - private List getTruncateQueries() { - return jdbcTemplate.queryForList( - "select concat('TRUNCATE TABLE ', table_name, ';') as truncate_statement" - + " from information_schema.tables" - + " where table_schema = 'everyonewaiter'" - + " and table_name != 'flyway_schema_history'", - String.class - ); - } - -} diff --git a/src/test/java/com/everyonewaiter/EveryonewaiterApiApplicationTest.java b/src/test/java/com/everyonewaiter/EveryonewaiterApiApplicationTest.java deleted file mode 100644 index a14d39f6..00000000 --- a/src/test/java/com/everyonewaiter/EveryonewaiterApiApplicationTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.everyonewaiter; - -import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.springframework.boot.SpringApplication; - -class EveryonewaiterApiApplicationTest { - - @Test - void run() { - try (MockedStatic mocked = Mockito.mockStatic(SpringApplication.class)) { - EveryonewaiterApiApplication.main(new String[0]); - - mocked.verify(() -> SpringApplication.run(EveryonewaiterApiApplication.class, new String[0])); - } - } - -} diff --git a/src/test/java/com/everyonewaiter/ExternalSystemTestConfiguration.java b/src/test/java/com/everyonewaiter/ExternalSystemTestConfiguration.java deleted file mode 100644 index 7ae89dd7..00000000 --- a/src/test/java/com/everyonewaiter/ExternalSystemTestConfiguration.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.everyonewaiter; - -import static com.everyonewaiter.domain.account.AccountFixture.createPasswordEncoder; -import static com.everyonewaiter.domain.notification.NotificationFixture.createEmailTemplateReader; - -import com.everyonewaiter.application.notification.required.AlimTalkSender; -import com.everyonewaiter.application.notification.required.DiscordWebhookSender; -import com.everyonewaiter.application.notification.required.EmailSender; -import com.everyonewaiter.domain.account.PasswordEncoder; -import com.everyonewaiter.domain.notification.EmailTemplateReader; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Primary; - -@TestConfiguration -class ExternalSystemTestConfiguration { - - @Bean - @Primary - PasswordEncoder passwordEncoder() { - return createPasswordEncoder(); - } - - @Bean - @Primary - AlimTalkSender alimTalkSender() { - return message -> System.out.println("AlimTalk Sent: " + message); - } - - @Bean - @Primary - EmailSender emailSender() { - return simpleEmail -> System.out.println("Email Sent: " + simpleEmail); - } - - @Bean - @Primary - EmailTemplateReader emailTemplateReader() { - return createEmailTemplateReader(); - } - - @Bean - @Primary - DiscordWebhookSender discordWebhookSender() { - return discordEmbeds -> System.out.println("Discord Sent: " + discordEmbeds); - } - -} diff --git a/src/test/java/com/everyonewaiter/IntegrationTest.java b/src/test/java/com/everyonewaiter/IntegrationTest.java deleted file mode 100644 index 608f4e8f..00000000 --- a/src/test/java/com/everyonewaiter/IntegrationTest.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.everyonewaiter; - -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.ActiveProfiles; - -@ActiveProfiles("test") -@SpringBootTest -@Import({TestContainerSupport.class, ExternalSystemTestConfiguration.class}) -@ExtendWith(DatabaseCleanUpExtension.class) -public abstract class IntegrationTest { - -} diff --git a/src/test/java/com/everyonewaiter/TestContainerCreator.java b/src/test/java/com/everyonewaiter/TestContainerCreator.java deleted file mode 100644 index bf2a06d0..00000000 --- a/src/test/java/com/everyonewaiter/TestContainerCreator.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.everyonewaiter; - -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.containers.MySQLContainer; -import org.testcontainers.utility.DockerImageName; - -class TestContainerCreator { - - static final String MYSQL_IMAGE_NAME = "mysql:8.4.3"; - static final String MYSQL_DATABASE_NAME = "everyonewaiter"; - static final String MYSQL_USERNAME = "root"; - static final String MYSQL_PASSWORD = "1234"; - - static final String REDIS_IMAGE_NAME = "redis:7.4.1-alpine"; - static final int REDIS_PORT = 6379; - static final String REDIS_PASSWORD = "1234"; - - static MySQLContainer createMysqlContainer() { - try (var container = new MySQLContainer<>(DockerImageName.parse(MYSQL_IMAGE_NAME))) { - return container.withDatabaseName(MYSQL_DATABASE_NAME) - .withUsername(MYSQL_USERNAME) - .withPassword(MYSQL_PASSWORD) - .withUrlParam("rewriteBatchedStatements", "true") - .withUrlParam("characterEncoding", "UTF-8"); - } - } - - static GenericContainer createRedisContainer() { - try (var container = new GenericContainer<>(DockerImageName.parse(REDIS_IMAGE_NAME))) { - return container - .withExposedPorts(REDIS_PORT) - .withCommand("redis-server", "--requirepass", REDIS_PASSWORD); - } - } - -} diff --git a/src/test/java/com/everyonewaiter/TestContainerSupport.java b/src/test/java/com/everyonewaiter/TestContainerSupport.java deleted file mode 100644 index 39bd59dd..00000000 --- a/src/test/java/com/everyonewaiter/TestContainerSupport.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.everyonewaiter; - -import static com.everyonewaiter.TestContainerCreator.REDIS_PASSWORD; - -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.testcontainers.service.connection.ServiceConnection; -import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.containers.MySQLContainer; - -@TestConfiguration -class TestContainerSupport { - - static final MySQLContainer MYSQL_CONTAINER = TestContainerCreator.createMysqlContainer(); - static final GenericContainer REDIS_CONTAINER = TestContainerCreator.createRedisContainer(); - - static { - MYSQL_CONTAINER.start(); - System.setProperty("spring.datasource.url", MYSQL_CONTAINER.getJdbcUrl()); - System.setProperty("spring.datasource.username", MYSQL_CONTAINER.getUsername()); - System.setProperty("spring.datasource.password", MYSQL_CONTAINER.getPassword()); - - REDIS_CONTAINER.start(); - System.setProperty("spring.data.redis.host", REDIS_CONTAINER.getHost()); - System.setProperty("spring.data.redis.port", REDIS_CONTAINER.getFirstMappedPort().toString()); - System.setProperty("spring.data.redis.password", REDIS_PASSWORD); - } - - @Bean - @ServiceConnection - MySQLContainer mysqlContainer() { - return MYSQL_CONTAINER; - } - - @Bean - @ServiceConnection(name = "redis") - GenericContainer redisContainer() { - return REDIS_CONTAINER; - } - -} diff --git a/src/test/java/com/everyonewaiter/application/account/provided/AccountCreateEventListener.java b/src/test/java/com/everyonewaiter/application/account/provided/AccountCreateEventListener.java deleted file mode 100644 index 0f7a962d..00000000 --- a/src/test/java/com/everyonewaiter/application/account/provided/AccountCreateEventListener.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.everyonewaiter.application.account.provided; - -import com.everyonewaiter.domain.account.AccountCreateEvent; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import org.springframework.context.event.EventListener; -import org.springframework.stereotype.Component; - -@Component -class AccountCreateEventListener { - - private final List events = new ArrayList<>(); - - @EventListener - public void consumeAccountCreateEvent(AccountCreateEvent event) { - events.add(event); - } - - public List getEvents() { - return Collections.unmodifiableList(events); - } - - public void clear() { - events.clear(); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/account/provided/AccountFinderTest.java b/src/test/java/com/everyonewaiter/application/account/provided/AccountFinderTest.java deleted file mode 100644 index 7879bdf6..00000000 --- a/src/test/java/com/everyonewaiter/application/account/provided/AccountFinderTest.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.everyonewaiter.application.account.provided; - -import static com.everyonewaiter.domain.account.AccountFixture.createAccountCreateRequest; -import static com.everyonewaiter.domain.account.AccountFixture.createPasswordEncoder; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; - -import com.everyonewaiter.IntegrationTest; -import com.everyonewaiter.application.account.required.AccountRepository; -import com.everyonewaiter.domain.account.Account; -import com.everyonewaiter.domain.account.AccountAdminPageRequest; -import com.everyonewaiter.domain.account.AccountAdminPageView; -import com.everyonewaiter.domain.account.AccountNotFoundException; -import com.everyonewaiter.domain.shared.Paging; -import com.everyonewaiter.domain.shared.PhoneNumber; -import jakarta.validation.ConstraintViolationException; -import java.util.Optional; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.Test; - -@RequiredArgsConstructor -class AccountFinderTest extends IntegrationTest { - - private final AccountFinder accountFinder; - private final AccountRepository accountRepository; - - @Test - void find() { - Account account = createAccount(); - - Optional found = accountFinder.find(account.getId()); - - assertThat(found).isPresent(); - assertThat(found.get().getId()).isEqualTo(account.getId()); - } - - @Test - void findByIdOrThrow() { - Account account = createAccount(); - - Account found = accountFinder.findOrThrow(account.getId()); - - assertThat(found.getId()).isEqualTo(account.getId()); - } - - @Test - void findByIdOrThrowFail() { - assertThatThrownBy(() -> accountFinder.findOrThrow(999L)) - .isInstanceOf(AccountNotFoundException.class); - } - - @Test - void findByPhoneOrThrow() { - Account account = createAccount(); - - Account found = accountFinder.findOrThrow(account.getPhoneNumber()); - - assertThat(found.getId()).isEqualTo(account.getId()); - } - - @Test - void findByPhoneOrThrowFail() { - assertThatThrownBy(() -> accountFinder.findOrThrow(new PhoneNumber("01087654321"))) - .isInstanceOf(AccountNotFoundException.class); - } - - @Test - void findAllByAdmin() { - Account account = createAccount(); - - Paging views = accountFinder.findAllByAdmin( - new AccountAdminPageRequest()); - - assertThat(views.getContent()).hasSize(1); - assertThat(views.getContent().getFirst().id()).isEqualTo(account.getId()); - } - - private Account createAccount() { - Account account = Account.create(createAccountCreateRequest(), createPasswordEncoder()); - - return accountRepository.save(account); - } - - @Test - void accountAdminReadRequestFail() { - checkValidation(new AccountAdminPageRequest(null, null, null, null, 0, 1)); - checkValidation(new AccountAdminPageRequest(null, null, null, null, 1, 0)); - } - - private void checkValidation(AccountAdminPageRequest readRequest) { - assertThatThrownBy(() -> accountFinder.findAllByAdmin(readRequest)) - .isInstanceOf(ConstraintViolationException.class); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/account/provided/AccountRegisterTest.java b/src/test/java/com/everyonewaiter/application/account/provided/AccountRegisterTest.java deleted file mode 100644 index afacbfa3..00000000 --- a/src/test/java/com/everyonewaiter/application/account/provided/AccountRegisterTest.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.everyonewaiter.application.account.provided; - -import static com.everyonewaiter.domain.account.AccountFixture.createAccountCreateRequest; -import static com.everyonewaiter.domain.auth.JwtFixedId.VERIFICATION_EMAIL_ID; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; - -import com.everyonewaiter.IntegrationTest; -import com.everyonewaiter.application.auth.required.JwtProvider; -import com.everyonewaiter.domain.account.Account; -import com.everyonewaiter.domain.account.AccountCreateEvent; -import com.everyonewaiter.domain.account.AccountCreateRequest; -import com.everyonewaiter.domain.account.AccountPermission; -import com.everyonewaiter.domain.account.AccountState; -import com.everyonewaiter.domain.account.AlreadyUseEmailException; -import com.everyonewaiter.domain.account.AlreadyUsePhoneException; -import com.everyonewaiter.domain.auth.ExpiredVerificationPhoneException; -import com.everyonewaiter.domain.auth.JwtPayload; -import jakarta.validation.ConstraintViolationException; -import java.time.Duration; -import java.time.Instant; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; -import org.springframework.data.redis.core.RedisTemplate; - -@RequiredArgsConstructor -class AccountRegisterTest extends IntegrationTest { - - private final RedisTemplate redisTemplate; - private final JwtProvider jwtProvider; - private final AccountRegister accountRegister; - private final AccountCreateEventListener accountCreateEventListener; - - @AfterEach - void cleanEvents() { - accountCreateEventListener.clear(); - } - - @Test - void register() { - Account account = createAccount(); - - assertThat(account.getState()).isEqualTo(AccountState.INACTIVE); - assertThat(account.getPermission()).isEqualTo(AccountPermission.USER); - assertThat(account.getLastSignIn()).isEqualTo(Instant.ofEpochMilli(0)); - - List events = accountCreateEventListener.getEvents(); - assertThat(events).hasSize(1); - assertThat(events.getFirst().email()).isEqualTo(account.getEmail()); - } - - @Test - void registerFail() { - assertThatThrownBy(() -> accountRegister.register(createAccountCreateRequest())) - .isInstanceOf(ExpiredVerificationPhoneException.class); - - createAccount(); - - assertThatThrownBy(() -> accountRegister.register(createAccountCreateRequest())) - .isInstanceOf(AlreadyUseEmailException.class); - - assertThatThrownBy(() -> accountRegister.register(createAccountCreateRequest("user@gmail.com"))) - .isInstanceOf(AlreadyUsePhoneException.class); - } - - @Test - void activate() { - Account account = createAccount(); - - JwtPayload payload = new JwtPayload(VERIFICATION_EMAIL_ID, account.getEmail().address()); - String token = jwtProvider.encode(payload, Duration.ofMinutes(10)); - - account = accountRegister.activate(token); - - assertThat(account.getState()).isEqualTo(AccountState.ACTIVE); - } - - private Account createAccount() { - redisTemplate.opsForValue().set("auth:success:01012345678", "-2"); - - return accountRegister.register(createAccountCreateRequest()); - } - - @Test - void accountCreateRequestFail() { - checkValidation(new AccountCreateRequest("admin@everyonewaiter", "@password1", "01012345678")); - checkValidation(new AccountCreateRequest("user@gmail.com", "@invalid", "01012345678")); - checkValidation(new AccountCreateRequest("user@gmail.com", "@password1", "0551234567")); - } - - private void checkValidation(AccountCreateRequest createRequest) { - assertThatThrownBy(() -> accountRegister.register(createRequest)) - .isInstanceOf(ConstraintViolationException.class); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/account/provided/AccountSignInHandlerTest.java b/src/test/java/com/everyonewaiter/application/account/provided/AccountSignInHandlerTest.java deleted file mode 100644 index 030c73ce..00000000 --- a/src/test/java/com/everyonewaiter/application/account/provided/AccountSignInHandlerTest.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.everyonewaiter.application.account.provided; - -import static com.everyonewaiter.domain.account.AccountFixture.createAccountCreateRequest; -import static com.everyonewaiter.domain.account.AccountFixture.createAccountSignInRequest; -import static com.everyonewaiter.domain.account.AccountFixture.createPasswordEncoder; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; - -import com.everyonewaiter.IntegrationTest; -import com.everyonewaiter.application.account.required.AccountRepository; -import com.everyonewaiter.application.auth.required.JwtProvider; -import com.everyonewaiter.domain.account.Account; -import com.everyonewaiter.domain.account.AccountSignInRequest; -import com.everyonewaiter.domain.account.AccountState; -import com.everyonewaiter.domain.account.FailedSignInException; -import com.everyonewaiter.domain.auth.JwtPayload; -import com.everyonewaiter.domain.auth.SignInToken; -import com.everyonewaiter.domain.auth.SignInTokenRenewRequest; -import com.everyonewaiter.domain.shared.AccessDeniedException; -import jakarta.validation.ConstraintViolationException; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.Test; -import org.springframework.test.util.ReflectionTestUtils; - -@RequiredArgsConstructor -class AccountSignInHandlerTest extends IntegrationTest { - - private final JwtProvider jwtProvider; - private final AccountRepository accountRepository; - private final AccountSignInHandler accountSignInHandler; - - @Test - void signIn() { - Account account = createAccount(); - - SignInToken signInToken = accountSignInHandler.signIn(createAccountSignInRequest()); - - JwtPayload payload = jwtProvider.decode(signInToken.accessToken()).orElseThrow(); - - assertThat(payload.id()).isEqualTo(account.getId()); - } - - @Test - void signInFail() { - assertThatThrownBy(() -> accountSignInHandler.signIn(createAccountSignInRequest())) - .isInstanceOf(FailedSignInException.class); - } - - @Test - void renew() { - Account account = createAccount(); - - var token = accountSignInHandler.signIn(createAccountSignInRequest()); - - var renew = accountSignInHandler.renew(new SignInTokenRenewRequest(token.refreshToken())); - - JwtPayload payload = jwtProvider.decode(renew.accessToken()).orElseThrow(); - - assertThat(payload.id()).isEqualTo(account.getId()); - } - - @Test - void renewFail() { - createAccount(); - - var token = accountSignInHandler.signIn(createAccountSignInRequest()); - - var request = new SignInTokenRenewRequest(token.refreshToken()); - - accountSignInHandler.renew(request); - - assertThatThrownBy(() -> accountSignInHandler.renew(request)) - .isInstanceOf(AccessDeniedException.class); - } - - private Account createAccount() { - Account account = Account.create(createAccountCreateRequest(), createPasswordEncoder()); - - ReflectionTestUtils.setField(account, "state", AccountState.ACTIVE); - - return accountRepository.save(account); - } - - @Test - void accountSignInRequestFail() { - checkValidation(new AccountSignInRequest("admin@everyonewaiter", "@password1")); - checkValidation(new AccountSignInRequest("user@gmail.com", "@invalid")); - } - - private void checkValidation(AccountSignInRequest signInRequest) { - assertThatThrownBy(() -> accountSignInHandler.signIn(signInRequest)) - .isInstanceOf(ConstraintViolationException.class); - } - - @Test - void signInTokenRenewRequestFail() { - checkValidation(new SignInTokenRenewRequest(null)); - checkValidation(new SignInTokenRenewRequest("")); - checkValidation(new SignInTokenRenewRequest(" ")); - } - - private void checkValidation(SignInTokenRenewRequest signInTokenRenewRequest) { - assertThatThrownBy(() -> accountSignInHandler.renew(signInTokenRenewRequest)) - .isInstanceOf(ConstraintViolationException.class); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/account/provided/AccountUpdaterTest.java b/src/test/java/com/everyonewaiter/application/account/provided/AccountUpdaterTest.java deleted file mode 100644 index fdfc9539..00000000 --- a/src/test/java/com/everyonewaiter/application/account/provided/AccountUpdaterTest.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.everyonewaiter.application.account.provided; - -import static com.everyonewaiter.domain.account.AccountFixture.createAccountAdminUpdateRequest; -import static com.everyonewaiter.domain.account.AccountFixture.createAccountCreateRequest; -import static com.everyonewaiter.domain.account.AccountFixture.createPasswordEncoder; -import static com.everyonewaiter.domain.account.AccountPermission.ADMIN; -import static com.everyonewaiter.domain.account.AccountPermission.OWNER; -import static com.everyonewaiter.domain.account.AccountState.ACTIVE; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; - -import com.everyonewaiter.IntegrationTest; -import com.everyonewaiter.application.account.required.AccountRepository; -import com.everyonewaiter.domain.account.Account; -import com.everyonewaiter.domain.account.AccountAdminUpdateRequest; -import com.everyonewaiter.domain.account.AccountNotFoundException; -import jakarta.validation.ConstraintViolationException; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.Test; -import org.springframework.test.util.ReflectionTestUtils; - -@RequiredArgsConstructor -class AccountUpdaterTest extends IntegrationTest { - - private final AccountUpdater accountUpdater; - private final AccountRepository accountRepository; - - @Test - void authorize() { - Account account = createAccount(); - - account = accountUpdater.authorize(account.getId(), OWNER); - - assertThat(account.getPermission()).isEqualTo(OWNER); - } - - @Test - void authorizeFail() { - assertThatThrownBy(() -> accountUpdater.authorize(999L, OWNER)) - .isInstanceOf(AccountNotFoundException.class); - } - - @Test - void updateByAdmin() { - Account adminAccount = createAccount(); - - ReflectionTestUtils.setField(adminAccount, "permission", ADMIN); - - Account userAccount = createAccount("user@gmail.com", "01087654321"); - - userAccount = accountUpdater.updateByAdmin( - adminAccount, - userAccount.getId(), - createAccountAdminUpdateRequest() - ); - - assertThat(userAccount.getState()).isEqualTo(ACTIVE); - assertThat(userAccount.getPermission()).isEqualTo(OWNER); - } - - private Account createAccount() { - return createAccount("admin@everyonewaiter.com", "01012345678"); - } - - private Account createAccount(String email, String phoneNumber) { - Account account = Account.create( - createAccountCreateRequest(email, phoneNumber), - createPasswordEncoder() - ); - - ReflectionTestUtils.setField(account, "state", ACTIVE); - - return accountRepository.save(account); - } - - @Test - void accountAdminUpdateRequestFail() { - checkValidation(new AccountAdminUpdateRequest(null, null)); - checkValidation(new AccountAdminUpdateRequest(ACTIVE, null)); - checkValidation(new AccountAdminUpdateRequest(null, OWNER)); - } - - private void checkValidation(AccountAdminUpdateRequest updateRequest) { - assertThatThrownBy(() -> accountUpdater.updateByAdmin(null, null, updateRequest)) - .isInstanceOf(ConstraintViolationException.class); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/account/provided/AccountValidatorTest.java b/src/test/java/com/everyonewaiter/application/account/provided/AccountValidatorTest.java deleted file mode 100644 index dfb6f162..00000000 --- a/src/test/java/com/everyonewaiter/application/account/provided/AccountValidatorTest.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.everyonewaiter.application.account.provided; - -import static com.everyonewaiter.domain.account.AccountFixture.createAccountCreateRequest; -import static com.everyonewaiter.domain.account.AccountFixture.createPasswordEncoder; -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; - -import com.everyonewaiter.IntegrationTest; -import com.everyonewaiter.application.account.required.AccountRepository; -import com.everyonewaiter.domain.account.Account; -import com.everyonewaiter.domain.account.AccountNotFoundException; -import com.everyonewaiter.domain.account.AccountPermission; -import com.everyonewaiter.domain.account.AccountState; -import com.everyonewaiter.domain.account.AlreadyUseEmailException; -import com.everyonewaiter.domain.account.AlreadyUsePhoneException; -import com.everyonewaiter.domain.account.AlreadyVerifiedEmailException; -import com.everyonewaiter.domain.shared.Email; -import com.everyonewaiter.domain.shared.PhoneNumber; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.Test; -import org.springframework.test.util.ReflectionTestUtils; - -@RequiredArgsConstructor -class AccountValidatorTest extends IntegrationTest { - - private final AccountValidator accountValidator; - private final AccountRepository accountRepository; - - @Test - void checkDuplicateEmail() { - Account account = createAccount(); - - assertThatCode(() -> accountValidator.checkDuplicateEmail(new Email("user@gmail.com"))) - .doesNotThrowAnyException(); - - assertThatThrownBy(() -> accountValidator.checkDuplicateEmail(account.getEmail())) - .isInstanceOf(AlreadyUseEmailException.class); - } - - @Test - void checkDuplicatePhone() { - Account account = createAccount(); - - assertThatCode(() -> accountValidator.checkDuplicatePhone(new PhoneNumber("01087654321"))) - .doesNotThrowAnyException(); - - assertThatThrownBy(() -> accountValidator.checkDuplicatePhone(account.getPhoneNumber())) - .isInstanceOf(AlreadyUsePhoneException.class); - } - - @Test - void checkPossibleSendAuthMail() { - Account account = createAccount(); - - assertThatCode(() -> accountValidator.checkPossibleSendAuthMail(account.getEmail())) - .doesNotThrowAnyException(); - } - - @Test - void checkPossibleSendAuthMailFail() { - Account account = createAccount(AccountState.ACTIVE, AccountPermission.USER); - - assertThatThrownBy(() -> accountValidator.checkPossibleSendAuthMail(account.getEmail())) - .isInstanceOf(AlreadyVerifiedEmailException.class); - } - - @Test - void checkPossibleSendAuthCode() { - Account account = createAccount(AccountState.ACTIVE, AccountPermission.OWNER); - - assertThatCode(() -> accountValidator.checkPossibleSendAuthCode(account.getPhoneNumber())) - .doesNotThrowAnyException(); - } - - @Test - void checkPossibleSendAuthCodeFail() { - Account account = createAccount(AccountState.INACTIVE, AccountPermission.OWNER); - - assertThatThrownBy(() -> accountValidator.checkPossibleSendAuthCode(account.getPhoneNumber())) - .isInstanceOf(AccountNotFoundException.class); - } - - private Account createAccount() { - return createAccount(AccountState.INACTIVE, AccountPermission.USER); - } - - private Account createAccount(AccountState state, AccountPermission permission) { - Account account = Account.create(createAccountCreateRequest(), createPasswordEncoder()); - - ReflectionTestUtils.setField(account, "state", state); - ReflectionTestUtils.setField(account, "permission", permission); - - return accountRepository.save(account); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/account/required/AccountRepositoryTest.java b/src/test/java/com/everyonewaiter/application/account/required/AccountRepositoryTest.java deleted file mode 100644 index 31e61769..00000000 --- a/src/test/java/com/everyonewaiter/application/account/required/AccountRepositoryTest.java +++ /dev/null @@ -1,207 +0,0 @@ -package com.everyonewaiter.application.account.required; - -import static com.everyonewaiter.domain.account.AccountFixture.createAccountCreateRequest; -import static com.everyonewaiter.domain.account.AccountFixture.createPasswordEncoder; -import static com.everyonewaiter.domain.account.AccountPermission.OWNER; -import static com.everyonewaiter.domain.account.AccountState.ACTIVE; -import static com.everyonewaiter.domain.account.AccountState.INACTIVE; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; - -import com.everyonewaiter.IntegrationTest; -import com.everyonewaiter.domain.account.Account; -import com.everyonewaiter.domain.account.AccountAdminPageRequest; -import com.everyonewaiter.domain.account.AccountAdminPageView; -import com.everyonewaiter.domain.account.AccountNotFoundException; -import com.everyonewaiter.domain.shared.Email; -import com.everyonewaiter.domain.shared.Paging; -import com.everyonewaiter.domain.shared.PhoneNumber; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.Test; - -@RequiredArgsConstructor -class AccountRepositoryTest extends IntegrationTest { - - private final AccountRepository accountRepository; - - @Test - void existsByEmail() { - Email email = new Email("admin@everyonewaiter.com"); - - assertThat(accountRepository.exists(email)).isFalse(); - - createAccount(); - - assertThat(accountRepository.exists(email)).isTrue(); - } - - @Test - void existsByEmailAndState() { - Account account = createAccount(); - - assertThat(accountRepository.exists(account.getEmail(), INACTIVE)).isTrue(); - assertThat(accountRepository.exists(account.getEmail(), ACTIVE)).isFalse(); - } - - @Test - void existsByPhone() { - PhoneNumber phoneNumber = new PhoneNumber("01012345678"); - - assertThat(accountRepository.exists(phoneNumber)).isFalse(); - - createAccount(); - - assertThat(accountRepository.exists(phoneNumber)).isTrue(); - } - - @Test - void existsByPhoneAndState() { - Account account = createAccount(); - - assertThat(accountRepository.exists(account.getPhoneNumber(), INACTIVE)).isTrue(); - assertThat(accountRepository.exists(account.getPhoneNumber(), ACTIVE)).isFalse(); - } - - @Test - void findAll() { - Account account = createAccount(); - - Paging pagedViews = findAll(new AccountAdminPageRequest()); - - assertThat(pagedViews.getContent()).hasSize(1); - assertThat(pagedViews.getContent().getFirst().id()).isEqualTo(account.getId()); - } - - @Test - void findAllWhereEmail() { - Account account = createAccount(); - - Paging pagedViews = findAll( - new AccountAdminPageRequest(account.getEmail().address(), null, null, null, 1, 20) - ); - - assertThat(pagedViews.getContent()).hasSize(1); - assertThat(pagedViews.getContent().getFirst().id()).isEqualTo(account.getId()); - - Paging emptyViews = findAll( - new AccountAdminPageRequest("user@everyonewaiter.com", null, null, null, 1, 20) - ); - - assertThat(emptyViews.getContent()).isEmpty(); - } - - @Test - void findAllWhereState() { - Account account = createAccount(); - - Paging pagedViews = findAll( - new AccountAdminPageRequest(null, account.getState(), null, null, 1, 20) - ); - - assertThat(pagedViews.getContent()).hasSize(1); - assertThat(pagedViews.getContent().getFirst().id()).isEqualTo(account.getId()); - - Paging emptyViews = findAll( - new AccountAdminPageRequest(null, ACTIVE, null, null, 1, 20) - ); - - assertThat(emptyViews.getContent()).isEmpty(); - } - - @Test - void findAllWherePermission() { - Account account = createAccount(); - - Paging pagedViews = findAll( - new AccountAdminPageRequest(null, null, account.getPermission(), null, 1, 20) - ); - - assertThat(pagedViews.getContent()).hasSize(1); - assertThat(pagedViews.getContent().getFirst().id()).isEqualTo(account.getId()); - - Paging emptyViews = findAll( - new AccountAdminPageRequest(null, null, OWNER, null, 1, 20) - ); - - assertThat(emptyViews.getContent()).isEmpty(); - } - - @Test - void findAllWhereHasStore() { - Account account = createAccount(); - - Paging pagedViews = findAll( - new AccountAdminPageRequest(null, null, null, false, 1, 20) - ); - - assertThat(pagedViews.getContent()).hasSize(1); - assertThat(pagedViews.getContent().getFirst().id()).isEqualTo(account.getId()); - - Paging emptyViews = findAll( - new AccountAdminPageRequest(null, null, null, true, 1, 20) - ); - - assertThat(emptyViews.getContent()).isEmpty(); - } - - @Test - void findById() { - Account account = createAccount(); - - assertThat(accountRepository.find(account.getId())).isPresent(); - assertThat(accountRepository.find(999L)).isEmpty(); - } - - @Test - void findByIdOrThrow() { - Account account = createAccount(); - - assertThatCode(() -> accountRepository.findOrThrow(account.getId())) - .doesNotThrowAnyException(); - - assertThatThrownBy(() -> accountRepository.findOrThrow(999L)) - .isInstanceOf(AccountNotFoundException.class); - } - - @Test - void findByEmail() { - Account account = createAccount(); - - assertThat(accountRepository.find(account.getEmail())).isPresent(); - assertThat(accountRepository.find(new Email("user@everyonewaiter.com"))).isEmpty(); - } - - @Test - void findByEmailOrThrow() { - Account account = createAccount(); - - assertThatCode(() -> accountRepository.findOrThrow(account.getEmail())) - .doesNotThrowAnyException(); - - assertThatThrownBy(() -> accountRepository.findOrThrow(new Email("user@gmail.com"))) - .isInstanceOf(AccountNotFoundException.class); - } - - @Test - void findByPhoneOrThrow() { - Account account = createAccount(); - - assertThatCode(() -> accountRepository.findOrThrow(account.getPhoneNumber())) - .doesNotThrowAnyException(); - - assertThatThrownBy(() -> accountRepository.findOrThrow(new PhoneNumber("01087654321"))) - .isInstanceOf(AccountNotFoundException.class); - } - - private Account createAccount() { - Account account = Account.create(createAccountCreateRequest(), createPasswordEncoder()); - - return accountRepository.save(account); - } - - private Paging findAll(AccountAdminPageRequest readRequest) { - return accountRepository.findAll(readRequest); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/auth/provided/AuthCodeSendEventListener.java b/src/test/java/com/everyonewaiter/application/auth/provided/AuthCodeSendEventListener.java deleted file mode 100644 index fb25551e..00000000 --- a/src/test/java/com/everyonewaiter/application/auth/provided/AuthCodeSendEventListener.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.everyonewaiter.application.auth.provided; - -import com.everyonewaiter.domain.auth.AuthCodeSendEvent; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import org.springframework.context.event.EventListener; -import org.springframework.stereotype.Component; - -@Component -class AuthCodeSendEventListener { - - private final List events = new ArrayList<>(); - - @EventListener - public void consumeAuthCodeSendEvent(AuthCodeSendEvent event) { - events.add(event); - } - - public List getEvents() { - return Collections.unmodifiableList(events); - } - - public void clear() { - events.clear(); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/auth/provided/AuthMailSendEventListener.java b/src/test/java/com/everyonewaiter/application/auth/provided/AuthMailSendEventListener.java deleted file mode 100644 index aa84c015..00000000 --- a/src/test/java/com/everyonewaiter/application/auth/provided/AuthMailSendEventListener.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.everyonewaiter.application.auth.provided; - -import com.everyonewaiter.domain.auth.AuthMailSendEvent; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import org.springframework.context.event.EventListener; -import org.springframework.stereotype.Component; - -@Component -class AuthMailSendEventListener { - - private final List events = new ArrayList<>(); - - @EventListener - public void consumeAuthMailSendEvent(AuthMailSendEvent event) { - events.add(event); - } - - public List getEvents() { - return Collections.unmodifiableList(events); - } - - public void clear() { - events.clear(); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/auth/provided/AuthenticatorTest.java b/src/test/java/com/everyonewaiter/application/auth/provided/AuthenticatorTest.java deleted file mode 100644 index 83c70fde..00000000 --- a/src/test/java/com/everyonewaiter/application/auth/provided/AuthenticatorTest.java +++ /dev/null @@ -1,238 +0,0 @@ -package com.everyonewaiter.application.auth.provided; - -import static com.everyonewaiter.domain.account.AccountState.ACTIVE; -import static com.everyonewaiter.domain.account.AccountState.INACTIVE; -import static com.everyonewaiter.domain.auth.AuthFixture.createSendAuthCodeRequest; -import static com.everyonewaiter.domain.auth.AuthFixture.createSendAuthMailRequest; -import static com.everyonewaiter.domain.auth.AuthFixture.createVerifyAuthCodeRequest; -import static com.everyonewaiter.domain.auth.AuthPurpose.CREATE_DEVICE; -import static com.everyonewaiter.domain.auth.AuthPurpose.SIGN_UP; -import static com.everyonewaiter.domain.auth.JwtFixedId.VERIFICATION_EMAIL_ID; -import static java.util.Objects.requireNonNull; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; - -import com.everyonewaiter.IntegrationTest; -import com.everyonewaiter.application.account.required.AccountRepository; -import com.everyonewaiter.application.auth.required.JwtProvider; -import com.everyonewaiter.domain.account.AccountNotFoundException; -import com.everyonewaiter.domain.account.AlreadyUsePhoneException; -import com.everyonewaiter.domain.account.AlreadyVerifiedEmailException; -import com.everyonewaiter.domain.auth.AlreadyVerifiedPhoneException; -import com.everyonewaiter.domain.auth.AuthCodeSendEvent; -import com.everyonewaiter.domain.auth.AuthMailSendEvent; -import com.everyonewaiter.domain.auth.ExceedMaximumVerificationException; -import com.everyonewaiter.domain.auth.ExpiredVerificationEmailException; -import com.everyonewaiter.domain.auth.ExpiredVerificationPhoneException; -import com.everyonewaiter.domain.auth.JwtPayload; -import com.everyonewaiter.domain.auth.SendAuthCodeRequest; -import com.everyonewaiter.domain.auth.SendAuthMailRequest; -import com.everyonewaiter.domain.auth.VerifyAuthCodeRequest; -import com.everyonewaiter.domain.shared.Email; -import com.everyonewaiter.domain.shared.PhoneNumber; -import jakarta.validation.ConstraintViolationException; -import java.util.List; -import java.util.Optional; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; - -@RequiredArgsConstructor -class AuthenticatorTest extends IntegrationTest { - - @MockitoSpyBean - private AccountRepository accountRepository; - - @MockitoSpyBean - private JwtProvider jwtProvider; - - private final RedisTemplate redisTemplate; - private final Authenticator authenticator; - private final AuthCodeSendEventListener authCodeSendEventListener; - private final AuthMailSendEventListener authMailSendEventListener; - - @AfterEach - void cleanEvents() { - authCodeSendEventListener.clear(); - authMailSendEventListener.clear(); - } - - @Test - void checkAuthSuccess() { - PhoneNumber phoneNumber = new PhoneNumber("01012345678"); - - // 인증 성공 내역 없는 경우 - assertThatThrownBy(() -> authenticator.checkAuthSuccess(SIGN_UP, phoneNumber)) - .isInstanceOf(ExpiredVerificationPhoneException.class); - - redisTemplate.opsForValue().set("auth:success:01012345678", "-2"); - - // 인증 성공 내역이 있는 경우 - assertThatCode(() -> authenticator.checkAuthSuccess(SIGN_UP, phoneNumber)) - .doesNotThrowAnyException(); - } - - @Test - void sendAuthCode() { - SendAuthCodeRequest sendAuthCodeRequest = createSendAuthCodeRequest(); - - authenticator.sendAuthCode(SIGN_UP, sendAuthCodeRequest); - - // 데이터 검증 - String authAttempt = redisTemplate.opsForValue().get("auth:attempt:sign_up:01012345678"); - String authCode = redisTemplate.opsForValue().get("auth:code:01012345678"); - boolean hasAuthSuccess = requireNonNull(redisTemplate.hasKey("auth:success:01012345678")); - - assertThat(authAttempt).isEqualTo("1"); - assertThat(hasAuthSuccess).isFalse(); - - // 도메인 이벤트 검증 - List events = authCodeSendEventListener.getEvents(); - assertThat(events).hasSize(1); - assertThat(events.getFirst().phoneNumber()).isEqualTo(new PhoneNumber("01012345678")); - assertThat(String.valueOf(events.getFirst().code())).isEqualTo(authCode); - } - - @Test - void sendAuthCodeImpossible() { - SendAuthCodeRequest sendAuthCodeRequest = createSendAuthCodeRequest(); - - when(accountRepository.exists(any(PhoneNumber.class))).thenReturn(true); - - assertThatThrownBy(() -> authenticator.sendAuthCode(SIGN_UP, sendAuthCodeRequest)) - .isInstanceOf(AlreadyUsePhoneException.class); - - when(accountRepository.exists(any(PhoneNumber.class), eq(ACTIVE))).thenReturn(false); - - assertThatThrownBy(() -> authenticator.sendAuthCode(CREATE_DEVICE, sendAuthCodeRequest)) - .isInstanceOf(AccountNotFoundException.class); - } - - @Test - void sendAuthCodeExceedMaxAttempt() { - SendAuthCodeRequest sendAuthCodeRequest = createSendAuthCodeRequest(); - - redisTemplate.opsForValue().set("auth:attempt:sign_up:01012345678", "5"); - - assertThatThrownBy(() -> authenticator.sendAuthCode(SIGN_UP, sendAuthCodeRequest)) - .isInstanceOf(ExceedMaximumVerificationException.class); - } - - @Test - void verifyAuthCode() { - VerifyAuthCodeRequest verifyAuthCodeRequest = createVerifyAuthCodeRequest(); - - redisTemplate.opsForValue().set("auth:code:01012345678", "123456"); - - PhoneNumber phoneNumber = authenticator.verifyAuthCode(SIGN_UP, verifyAuthCodeRequest); - - boolean hasAuthSuccess = requireNonNull(redisTemplate.hasKey("auth:success:01012345678")); - boolean hasAuthCode = requireNonNull(redisTemplate.hasKey("auth:code:01012345678")); - - assertThat(phoneNumber.value()).isEqualTo("01012345678"); - assertThat(hasAuthSuccess).isTrue(); - assertThat(hasAuthCode).isFalse(); - } - - @Test - void verifyAuthCodeFail() { - VerifyAuthCodeRequest verifyAuthCodeRequest = createVerifyAuthCodeRequest(); - - redisTemplate.opsForValue().set("auth:success:01012345678", "-2"); - - assertThatThrownBy(() -> authenticator.verifyAuthCode(SIGN_UP, verifyAuthCodeRequest)) - .isInstanceOf(AlreadyVerifiedPhoneException.class); - } - - @Test - void sendAuthMail() { - SendAuthMailRequest sendAuthMailRequest = createSendAuthMailRequest(); - - when(accountRepository.exists(any(Email.class), eq(INACTIVE))).thenReturn(true); - - authenticator.sendAuthMail(sendAuthMailRequest); - - // 도메인 이벤트 검증 - List events = authMailSendEventListener.getEvents(); - assertThat(events).hasSize(1); - assertThat(events.getFirst().email()).isEqualTo(new Email("admin@everyonewaiter.com")); - } - - @Test - void sendAuthMailFail() { - SendAuthMailRequest sendAuthMailRequest = createSendAuthMailRequest(); - - when(accountRepository.exists(any(Email.class), eq(INACTIVE))).thenReturn(false); - - assertThatThrownBy(() -> authenticator.sendAuthMail(sendAuthMailRequest)) - .isInstanceOf(AlreadyVerifiedEmailException.class); - } - - @Test - void verifyAuthMail() { - JwtPayload payload = new JwtPayload(VERIFICATION_EMAIL_ID, "admin@everyonewaiter.com"); - - when(jwtProvider.decode("valid token")).thenReturn(Optional.of(payload)); - - Email email = authenticator.verifyAuthMail("valid token"); - - assertThat(email.address()).isEqualTo(payload.subject()); - } - - @Test - void verifyAuthMailFail() { - JwtPayload payload = new JwtPayload(VERIFICATION_EMAIL_ID - 1, "admin@everyonewaiter.com"); - - when(jwtProvider.decode("valid token")).thenReturn(Optional.of(payload)); - - assertThatThrownBy(() -> authenticator.verifyAuthMail("valid token")) - .isInstanceOf(ExpiredVerificationEmailException.class); - - when(jwtProvider.decode("invalid token")).thenReturn(Optional.empty()); - - assertThatThrownBy(() -> authenticator.verifyAuthMail("invalid token")) - .isInstanceOf(ExpiredVerificationEmailException.class); - } - - @Test - void sendAuthCodeRequestFail() { - checkValidation(new SendAuthCodeRequest("0551234567")); - } - - private void checkValidation(SendAuthCodeRequest sendAuthCodeRequest) { - assertThatThrownBy(() -> authenticator.sendAuthCode(SIGN_UP, sendAuthCodeRequest)) - .isInstanceOf(ConstraintViolationException.class); - } - - @Test - @SuppressWarnings("DataFlowIssue") - void verifyAuthCodeRequestFail() { - checkValidation(new VerifyAuthCodeRequest("0551234567", 123456)); - checkValidation(new VerifyAuthCodeRequest("01012345678", 99999)); - checkValidation(new VerifyAuthCodeRequest("01012345678", 1000000)); - } - - private void checkValidation(VerifyAuthCodeRequest verifyAuthCodeRequest) { - assertThatThrownBy(() -> authenticator.verifyAuthCode(SIGN_UP, verifyAuthCodeRequest)) - .isInstanceOf(ConstraintViolationException.class); - } - - @Test - void sendAuthMailRequestFail() { - checkValidation(new SendAuthMailRequest("admin@everyonewaiter")); - checkValidation(new SendAuthMailRequest("admineveryonewaiter")); - checkValidation(new SendAuthMailRequest("@everyonewaiter")); - } - - private void checkValidation(SendAuthMailRequest sendAuthMailRequest) { - assertThatThrownBy(() -> authenticator.sendAuthMail(sendAuthMailRequest)) - .isInstanceOf(ConstraintViolationException.class); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/auth/provided/SignInTokenProviderTest.java b/src/test/java/com/everyonewaiter/application/auth/provided/SignInTokenProviderTest.java deleted file mode 100644 index 80ab6e30..00000000 --- a/src/test/java/com/everyonewaiter/application/auth/provided/SignInTokenProviderTest.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.everyonewaiter.application.auth.provided; - -import static com.everyonewaiter.domain.auth.AuthFixture.createSignInTokenRenewRequest; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; - -import com.everyonewaiter.IntegrationTest; -import com.everyonewaiter.application.auth.required.JwtProvider; -import com.everyonewaiter.domain.auth.JwtPayload; -import com.everyonewaiter.domain.auth.RefreshToken; -import com.everyonewaiter.domain.auth.SignInToken; -import com.everyonewaiter.domain.auth.SignInTokenRenewRequest; -import com.everyonewaiter.domain.shared.AuthenticationException; -import jakarta.persistence.EntityManager; -import jakarta.validation.ConstraintViolationException; -import java.util.Optional; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.Test; - -@RequiredArgsConstructor -class SignInTokenProviderTest extends IntegrationTest { - - private final EntityManager entityManager; - private final JwtProvider jwtProvider; - private final SignInTokenProvider signInTokenProvider; - - @Test - void createToken() { - SignInToken signInToken = signInTokenProvider.createToken(1L); - - JwtPayload accPayload = jwtProvider.decode(signInToken.accessToken()).orElseThrow(); - JwtPayload refPayload = jwtProvider.decode(signInToken.refreshToken()).orElseThrow(); - - assertThat(accPayload.id()).isEqualTo(1L); - assertThat(Long.parseLong(accPayload.subject())).isEqualTo(refPayload.id()); - assertThat(Long.parseLong(refPayload.subject())).isEqualTo(refPayload.id()); - } - - @Test - void renewToken() { - var token = signInTokenProvider.createToken(1L); - - var request = createSignInTokenRenewRequest(token.refreshToken()); - - SignInToken signInToken = signInTokenProvider.renewToken(request).orElseThrow(); - - JwtPayload accPayload = jwtProvider.decode(signInToken.accessToken()).orElseThrow(); - JwtPayload refPayload = jwtProvider.decode(signInToken.refreshToken()).orElseThrow(); - - assertThat(accPayload.id()).isEqualTo(1L); - assertThat(accPayload.subject()).isEqualTo(refPayload.subject()); - assertThat(refPayload.id()).isNotEqualTo(Long.parseLong(refPayload.subject())); - } - - @Test - void renewTokenFailByDecode() { - var request = createSignInTokenRenewRequest("invalid token"); - - assertThatThrownBy(() -> signInTokenProvider.renewToken(request)) - .isInstanceOf(AuthenticationException.class); - } - - @Test - void renewTokenFailBySteal() { - var token = signInTokenProvider.createToken(1L); - - var request = createSignInTokenRenewRequest(token.refreshToken()); - - SignInToken successSignInToken = signInTokenProvider.renewToken(request).orElseThrow(); - - // 이미 갱신된 리프레시 토큰으로 갱신 요청 시 토큰이 탈취되었다고 판단 - Optional failSignInToken = signInTokenProvider.renewToken(request); - - var refreshTokenId = jwtProvider.decode(successSignInToken.refreshToken()).orElseThrow().id(); - var refreshToken = entityManager.find(RefreshToken.class, refreshTokenId); - - assertThat(failSignInToken).isEmpty(); - assertThat(refreshToken).isNull(); - } - - @Test - void signInTokenRenewRequestFail() { - checkValidation(new SignInTokenRenewRequest(null)); - checkValidation(new SignInTokenRenewRequest("")); - checkValidation(new SignInTokenRenewRequest(" ")); - } - - private void checkValidation(SignInTokenRenewRequest signInTokenRenewRequest) { - assertThatThrownBy(() -> signInTokenProvider.renewToken(signInTokenRenewRequest)) - .isInstanceOf(ConstraintViolationException.class); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/auth/required/AuthRepositoryTest.java b/src/test/java/com/everyonewaiter/application/auth/required/AuthRepositoryTest.java deleted file mode 100644 index e0781615..00000000 --- a/src/test/java/com/everyonewaiter/application/auth/required/AuthRepositoryTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.everyonewaiter.application.auth.required; - -import static com.everyonewaiter.domain.auth.AuthFixture.createAuthAttempt; -import static com.everyonewaiter.domain.auth.AuthFixture.createAuthCode; -import static com.everyonewaiter.domain.auth.AuthFixture.createAuthSuccess; -import static org.assertj.core.api.Assertions.assertThat; - -import com.everyonewaiter.IntegrationTest; -import com.everyonewaiter.domain.auth.AuthAttempt; -import com.everyonewaiter.domain.auth.AuthCode; -import com.everyonewaiter.domain.auth.AuthSuccess; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.Test; -import org.springframework.data.redis.core.RedisTemplate; - -@RequiredArgsConstructor -class AuthRepositoryTest extends IntegrationTest { - - private final AuthRepository authRepository; - private final RedisTemplate redisTemplate; - - @Test - void exists() { - AuthCode authCode = createAuthCode(); - - assertThat(authRepository.exists(authCode)).isFalse(); - - authRepository.save(authCode); - - assertThat(authRepository.exists(authCode)).isTrue(); - } - - @Test - void find() { - AuthCode authCode = createAuthCode(); - - assertThat(authRepository.find(authCode)).isZero(); - - authRepository.save(authCode); - - assertThat(authRepository.find(authCode)).isEqualTo(123456); - } - - @Test - void increment() { - AuthAttempt authAttempt = createAuthAttempt(); - - assertThat(redisTemplate.getExpire(authAttempt.key())).isEqualTo(-2); - - authRepository.increment(authAttempt); - - assertThat(authRepository.find(authAttempt)).isEqualTo(1); - assertThat(redisTemplate.getExpire(authAttempt.key())).isNotEqualTo(-2); - - authRepository.increment(authAttempt); - - assertThat(authRepository.find(authAttempt)).isEqualTo(2); - } - - @Test - void delete() { - AuthSuccess authSuccess = createAuthSuccess(); - - authRepository.save(authSuccess); - - assertThat(redisTemplate.hasKey(authSuccess.key())).isTrue(); - - authRepository.delete(authSuccess); - - assertThat(redisTemplate.hasKey(authSuccess.key())).isFalse(); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/auth/required/JwtProviderTest.java b/src/test/java/com/everyonewaiter/application/auth/required/JwtProviderTest.java deleted file mode 100644 index b6a19324..00000000 --- a/src/test/java/com/everyonewaiter/application/auth/required/JwtProviderTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.everyonewaiter.application.auth.required; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.everyonewaiter.IntegrationTest; -import com.everyonewaiter.domain.auth.JwtPayload; -import java.time.Duration; -import java.util.Optional; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.Test; - -@RequiredArgsConstructor -class JwtProviderTest extends IntegrationTest { - - private final JwtProvider jwtProvider; - - @Test - void jwtProvider() { - JwtPayload payload = new JwtPayload(1L, "1"); - - String encoded = jwtProvider.encode(payload, Duration.ofMinutes(5)); - - Optional decoded = jwtProvider.decode(encoded); - assertThat(decoded).isPresent(); - assertThat(decoded.get().id()).isEqualTo(1L); - assertThat(decoded.get().subject()).isEqualTo("1"); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/auth/required/RefreshTokenRepositoryTest.java b/src/test/java/com/everyonewaiter/application/auth/required/RefreshTokenRepositoryTest.java deleted file mode 100644 index 3a199769..00000000 --- a/src/test/java/com/everyonewaiter/application/auth/required/RefreshTokenRepositoryTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.everyonewaiter.application.auth.required; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; - -import com.everyonewaiter.IntegrationTest; -import com.everyonewaiter.domain.auth.RefreshToken; -import com.everyonewaiter.domain.shared.AuthenticationException; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.Test; - -@RequiredArgsConstructor -class RefreshTokenRepositoryTest extends IntegrationTest { - - private final RefreshTokenRepository refreshTokenRepository; - - @Test - void findByIdOrThrow() { - RefreshToken refreshToken = createRefreshToken(); - - RefreshToken found = refreshTokenRepository.findByIdOrThrow(refreshToken.getId()); - - assertThat(found.getId()).isEqualTo(refreshToken.getId()); - assertThat(found.getAccountId()).isEqualTo(refreshToken.getAccountId()); - assertThat(found.getCurrentTokenId()).isEqualTo(refreshToken.getCurrentTokenId()); - } - - @Test - void findByIdOrThrowFail() { - assertThatThrownBy(() -> refreshTokenRepository.findByIdOrThrow(999L)) - .isInstanceOf(AuthenticationException.class); - } - - @Test - void delete() { - RefreshToken refreshToken = createRefreshToken(); - - refreshTokenRepository.delete(refreshToken); - - assertThatThrownBy(() -> refreshTokenRepository.findByIdOrThrow(refreshToken.getId())) - .isInstanceOf(AuthenticationException.class); - } - - private RefreshToken createRefreshToken() { - RefreshToken refreshToken = RefreshToken.create(1L); - - return refreshTokenRepository.save(refreshToken); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/auth/required/SignatureEncoderTest.java b/src/test/java/com/everyonewaiter/application/auth/required/SignatureEncoderTest.java deleted file mode 100644 index dd5d0815..00000000 --- a/src/test/java/com/everyonewaiter/application/auth/required/SignatureEncoderTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.everyonewaiter.application.auth.required; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.everyonewaiter.IntegrationTest; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.Test; - -@RequiredArgsConstructor -class SignatureEncoderTest extends IntegrationTest { - - private final SignatureEncoder signatureEncoder; - - @Test - void signatureEncoder() { - String encoded = signatureEncoder.encode("awesome", "secret"); - - assertThat(signatureEncoder.matches(encoded, "awesome", "secret")).isTrue(); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/health/provided/HealthCheckCreatorTest.java b/src/test/java/com/everyonewaiter/application/health/provided/HealthCheckCreatorTest.java deleted file mode 100644 index f9aaf07a..00000000 --- a/src/test/java/com/everyonewaiter/application/health/provided/HealthCheckCreatorTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.everyonewaiter.application.health.provided; - -import static com.everyonewaiter.domain.health.ApkVersionFixture.createApkVersionCreateRequest; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; - -import com.everyonewaiter.IntegrationTest; -import com.everyonewaiter.domain.health.ApkVersion; -import com.everyonewaiter.domain.health.ApkVersionCreateRequest; -import jakarta.validation.ConstraintViolationException; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.Test; - -@RequiredArgsConstructor -class HealthCheckCreatorTest extends IntegrationTest { - - private final HealthCheckCreator healthCheckCreator; - - @Test - void createApkVersion() { - ApkVersionCreateRequest createRequest = createApkVersionCreateRequest(); - - ApkVersion apkVersion = healthCheckCreator.createApkVersion(createRequest); - - assertThat(apkVersion.getId()).isNotNull(); - } - - @Test - @SuppressWarnings("DataFlowIssue") - void createApkVersionRequestFail() { - checkValidation(new ApkVersionCreateRequest(0, 0, 0, "")); - checkValidation(new ApkVersionCreateRequest(1, 101, 0, "")); - checkValidation(new ApkVersionCreateRequest(1, 0, 101, "")); - checkValidation(new ApkVersionCreateRequest(1, 0, 0, null)); - } - - private void checkValidation(ApkVersionCreateRequest createRequest) { - assertThatThrownBy(() -> healthCheckCreator.createApkVersion(createRequest)) - .isInstanceOf(ConstraintViolationException.class); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/health/provided/HealthCheckFinderTest.java b/src/test/java/com/everyonewaiter/application/health/provided/HealthCheckFinderTest.java deleted file mode 100644 index 41810002..00000000 --- a/src/test/java/com/everyonewaiter/application/health/provided/HealthCheckFinderTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.everyonewaiter.application.health.provided; - -import static com.everyonewaiter.domain.health.ApkVersionFixture.createApkVersionCreateRequest; -import static org.assertj.core.api.Assertions.assertThat; - -import com.everyonewaiter.IntegrationTest; -import com.everyonewaiter.domain.health.ApkVersion; -import com.everyonewaiter.domain.health.ServerInfo; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.Test; -import org.springframework.boot.info.BuildProperties; - -@RequiredArgsConstructor -class HealthCheckFinderTest extends IntegrationTest { - - private final BuildProperties buildProperties; - private final HealthCheckCreator healthCheckCreator; - private final HealthCheckFinder healthCheckFinder; - - @Test - void findServerInfo() { - ServerInfo serverVersion = healthCheckFinder.findServerInfo(); - - assertThat(serverVersion.version()).isEqualTo(buildProperties.getVersion()); - assertThat(serverVersion.group()).isEqualTo(buildProperties.getGroup()); - assertThat(serverVersion.artifact()).isEqualTo(buildProperties.getArtifact()); - } - - @Test - void findLatestApkVersion() { - ApkVersion apkVersion = healthCheckCreator.createApkVersion(createApkVersionCreateRequest()); - - ApkVersion latestApkVersion = healthCheckFinder.findLatestApkVersion(); - - assertThat(latestApkVersion).isEqualTo(apkVersion); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/health/required/ApkVersionRepositoryTest.java b/src/test/java/com/everyonewaiter/application/health/required/ApkVersionRepositoryTest.java deleted file mode 100644 index 146d45df..00000000 --- a/src/test/java/com/everyonewaiter/application/health/required/ApkVersionRepositoryTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.everyonewaiter.application.health.required; - -import static com.everyonewaiter.domain.health.ApkVersionFixture.createApkVersionCreateRequest; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; - -import com.everyonewaiter.IntegrationTest; -import com.everyonewaiter.domain.health.ApkVersion; -import com.everyonewaiter.domain.health.ApkVersionNotFoundException; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.Test; - -@RequiredArgsConstructor -class ApkVersionRepositoryTest extends IntegrationTest { - - private final ApkVersionRepository apkVersionRepository; - - @Test - void findLatest() { - ApkVersion apkVersion = ApkVersion.create(createApkVersionCreateRequest()); - apkVersionRepository.save(apkVersion); - - ApkVersion found = apkVersionRepository.findLatest(); - - assertThat(found.getId()).isNotNull(); - assertThat(found.getId()).isEqualTo(apkVersion.getId()); - } - - @Test - void findLatestFail() { - assertThatThrownBy(apkVersionRepository::findLatest) - .isInstanceOf(ApkVersionNotFoundException.class); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/notification/provided/NotificationSenderTest.java b/src/test/java/com/everyonewaiter/application/notification/provided/NotificationSenderTest.java deleted file mode 100644 index 2cb74720..00000000 --- a/src/test/java/com/everyonewaiter/application/notification/provided/NotificationSenderTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.everyonewaiter.application.notification.provided; - -import static com.everyonewaiter.domain.notification.NotificationFixture.createAlimTalkMessage; -import static com.everyonewaiter.domain.notification.NotificationFixture.createDiscordEmbeds; -import static com.everyonewaiter.domain.notification.NotificationFixture.createTemplateEmail; -import static org.assertj.core.api.Assertions.assertThat; - -import com.everyonewaiter.IntegrationTest; -import com.everyonewaiter.domain.notification.AlimTalkMessage; -import com.everyonewaiter.domain.notification.DiscordEmbeds; -import com.everyonewaiter.domain.notification.EmailTemplateReader; -import com.everyonewaiter.domain.notification.TemplateEmail; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.Test; -import org.junitpioneer.jupiter.StdIo; -import org.junitpioneer.jupiter.StdOut; - -@RequiredArgsConstructor -class NotificationSenderTest extends IntegrationTest { - - private final NotificationSender notificationSender; - private final EmailTemplateReader emailTemplateReader; - - @Test - @StdIo - void sendAlimTalkOneToOne(StdOut stdOut) { - AlimTalkMessage alimTalkMessage = createAlimTalkMessage(); - - notificationSender.sendAlimTalkOneToOne(alimTalkMessage); - - assertThat(stdOut.capturedString()) - .isEqualTo("AlimTalk Sent: " + alimTalkMessage + System.lineSeparator()); - } - - @Test - @StdIo - void sendEmailOneToOne(StdOut stdOut) { - TemplateEmail templateEmail = createTemplateEmail(); - - notificationSender.sendEmailOneToOne(templateEmail); - - assertThat(stdOut.capturedLines()[0]) - .isEqualTo("Email Sent: " + templateEmail.toSimpleEmail(emailTemplateReader)); - } - - @Test - @StdIo - void sendDiscord(StdOut stdOut) { - DiscordEmbeds embeds = createDiscordEmbeds(); - - notificationSender.sendDiscord(embeds); - - assertThat(stdOut.capturedLines()[0]).isEqualTo("Discord Sent: " + embeds); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/notification/required/AlimTalkSenderTest.java b/src/test/java/com/everyonewaiter/application/notification/required/AlimTalkSenderTest.java deleted file mode 100644 index 421c12e5..00000000 --- a/src/test/java/com/everyonewaiter/application/notification/required/AlimTalkSenderTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.everyonewaiter.application.notification.required; - -import static com.everyonewaiter.domain.notification.NotificationFixture.createAlimTalkMessage; -import static org.assertj.core.api.Assertions.assertThat; - -import com.everyonewaiter.IntegrationTest; -import com.everyonewaiter.domain.notification.AlimTalkMessage; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.Test; -import org.junitpioneer.jupiter.StdIo; -import org.junitpioneer.jupiter.StdOut; - -@RequiredArgsConstructor -class AlimTalkSenderTest extends IntegrationTest { - - private final AlimTalkSender alimTalkSender; - - @Test - @StdIo - void send(StdOut stdOut) { - AlimTalkMessage alimTalkMessage = createAlimTalkMessage(); - - alimTalkSender.send(alimTalkMessage); - - assertThat(stdOut.capturedString()) - .isEqualTo("AlimTalk Sent: " + alimTalkMessage + System.lineSeparator()); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/notification/required/DiscordWebhookSenderTest.java b/src/test/java/com/everyonewaiter/application/notification/required/DiscordWebhookSenderTest.java deleted file mode 100644 index 455a5c99..00000000 --- a/src/test/java/com/everyonewaiter/application/notification/required/DiscordWebhookSenderTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.everyonewaiter.application.notification.required; - -import static com.everyonewaiter.domain.notification.NotificationFixture.createDiscordEmbeds; -import static org.assertj.core.api.Assertions.assertThat; - -import com.everyonewaiter.IntegrationTest; -import com.everyonewaiter.domain.notification.DiscordEmbeds; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.Test; -import org.junitpioneer.jupiter.StdIo; -import org.junitpioneer.jupiter.StdOut; - -@RequiredArgsConstructor -class DiscordWebhookSenderTest extends IntegrationTest { - - private final DiscordWebhookSender discordWebhookSender; - - @Test - @StdIo - void send(StdOut stdOut) { - DiscordEmbeds embeds = createDiscordEmbeds(); - - discordWebhookSender.send(embeds); - - assertThat(stdOut.capturedLines()[0]).isEqualTo("Discord Sent: " + embeds); - } - -} diff --git a/src/test/java/com/everyonewaiter/application/notification/required/EmailSenderTest.java b/src/test/java/com/everyonewaiter/application/notification/required/EmailSenderTest.java deleted file mode 100644 index f037d6ef..00000000 --- a/src/test/java/com/everyonewaiter/application/notification/required/EmailSenderTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.everyonewaiter.application.notification.required; - -import static com.everyonewaiter.domain.notification.NotificationFixture.createSimpleEmail; -import static org.assertj.core.api.Assertions.assertThat; - -import com.everyonewaiter.IntegrationTest; -import com.everyonewaiter.domain.notification.SimpleEmail; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.Test; -import org.junitpioneer.jupiter.StdIo; -import org.junitpioneer.jupiter.StdOut; - -@RequiredArgsConstructor -class EmailSenderTest extends IntegrationTest { - - private final EmailSender emailSender; - - @Test - @StdIo - void send(StdOut stdOut) { - SimpleEmail simpleEmail = createSimpleEmail(); - - emailSender.send(simpleEmail); - - assertThat(stdOut.capturedLines()[0]).isEqualTo("Email Sent: " + simpleEmail); - } - -} From 405207a5375ed24c4afcf1199eecfd2603aa1f36 Mon Sep 17 00:00:00 2001 From: handwoong Date: Wed, 31 Dec 2025 22:15:36 +0900 Subject: [PATCH 3/6] =?UTF-8?q?remove:=20=EB=A9=94=EB=89=B4=20=EC=BA=90?= =?UTF-8?q?=EC=8B=B1=20=EA=B8=B0=EB=8A=A5=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integration/CacheConfiguration.java | 46 ------------------- .../menu/CategoryModifyService.java | 6 --- .../menu/CategoryQueryService.java | 3 -- .../application/menu/MenuModifyService.java | 8 ---- .../application/support/CacheName.java | 12 ----- 5 files changed, 75 deletions(-) delete mode 100644 src/main/java/com/everyonewaiter/adapter/integration/CacheConfiguration.java delete mode 100644 src/main/java/com/everyonewaiter/application/support/CacheName.java diff --git a/src/main/java/com/everyonewaiter/adapter/integration/CacheConfiguration.java b/src/main/java/com/everyonewaiter/adapter/integration/CacheConfiguration.java deleted file mode 100644 index cd1356dd..00000000 --- a/src/main/java/com/everyonewaiter/adapter/integration/CacheConfiguration.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.everyonewaiter.adapter.integration; - -import java.time.Duration; -import org.springframework.cache.CacheManager; -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.cache.RedisCacheManager; -import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; -import org.springframework.data.redis.serializer.GenericJacksonJsonRedisSerializer; -import org.springframework.data.redis.serializer.RedisSerializationContext; -import org.springframework.data.redis.serializer.StringRedisSerializer; -import tools.jackson.databind.json.JsonMapper; - -@Configuration -@EnableCaching -class CacheConfiguration { - - @Bean - public CacheManager cacheManager( - LettuceConnectionFactory connectionFactory, - RedisCacheConfiguration redisCacheConfiguration - ) { - return RedisCacheManager.RedisCacheManagerBuilder - .fromConnectionFactory(connectionFactory) - .cacheDefaults(redisCacheConfiguration) - .build(); - } - - @Bean - public RedisCacheConfiguration redisCacheConfiguration(JsonMapper jsonMapper) { - return RedisCacheConfiguration.defaultCacheConfig() - .disableCachingNullValues() - .serializeKeysWith( - RedisSerializationContext.SerializationPair - .fromSerializer(new StringRedisSerializer()) - ) - .serializeValuesWith( - RedisSerializationContext.SerializationPair - .fromSerializer(new GenericJacksonJsonRedisSerializer(jsonMapper)) - ) - .entryTtl(Duration.ofHours(3)); - } - -} diff --git a/src/main/java/com/everyonewaiter/application/menu/CategoryModifyService.java b/src/main/java/com/everyonewaiter/application/menu/CategoryModifyService.java index 4520459c..1df45f28 100644 --- a/src/main/java/com/everyonewaiter/application/menu/CategoryModifyService.java +++ b/src/main/java/com/everyonewaiter/application/menu/CategoryModifyService.java @@ -4,7 +4,6 @@ import com.everyonewaiter.application.menu.provided.CategoryManager; import com.everyonewaiter.application.menu.required.CategoryRepository; import com.everyonewaiter.application.store.provided.StoreFinder; -import com.everyonewaiter.application.support.CacheName; import com.everyonewaiter.application.support.DistributedLock; import com.everyonewaiter.domain.menu.AlreadyUseCategoryNameException; import com.everyonewaiter.domain.menu.Category; @@ -14,7 +13,6 @@ import com.everyonewaiter.domain.menu.ExceedMaxCategoryCountException; import com.everyonewaiter.domain.store.Store; import lombok.RequiredArgsConstructor; -import org.springframework.cache.annotation.CacheEvict; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -31,7 +29,6 @@ class CategoryModifyService implements CategoryManager { @Override @DistributedLock(key = "#storeId + '-menu'") - @CacheEvict(cacheNames = CacheName.STORE_MENU, key = "#storeId") public Category create(Long storeId, CategoryCreateRequest createRequest) { validateCategoryCreate(storeId, createRequest); @@ -57,7 +54,6 @@ private void validateCategoryCreate(Long storeId, CategoryCreateRequest createRe @Override @DistributedLock(key = "#storeId + '-menu'") - @CacheEvict(cacheNames = CacheName.STORE_MENU, key = "#storeId") public Category update(Long categoryId, Long storeId, CategoryUpdateRequest updateRequest) { validateCategoryUpdate(categoryId, storeId, updateRequest); @@ -80,7 +76,6 @@ private void validateCategoryUpdate( @Override @DistributedLock(key = "#storeId + '-menu'") - @CacheEvict(cacheNames = CacheName.STORE_MENU, key = "#storeId") public Category movePosition( Long sourceId, Long targetId, @@ -100,7 +95,6 @@ public Category movePosition( @Override @DistributedLock(key = "#storeId + '-menu'") - @CacheEvict(cacheNames = CacheName.STORE_MENU, key = "#storeId") public void delete(Long categoryId, Long storeId) { Category category = categoryFinder.findOrThrow(categoryId, storeId); diff --git a/src/main/java/com/everyonewaiter/application/menu/CategoryQueryService.java b/src/main/java/com/everyonewaiter/application/menu/CategoryQueryService.java index 15151c41..409ca6d7 100644 --- a/src/main/java/com/everyonewaiter/application/menu/CategoryQueryService.java +++ b/src/main/java/com/everyonewaiter/application/menu/CategoryQueryService.java @@ -2,13 +2,11 @@ import com.everyonewaiter.application.menu.provided.CategoryFinder; import com.everyonewaiter.application.menu.required.CategoryRepository; -import com.everyonewaiter.application.support.CacheName; import com.everyonewaiter.application.support.ReadOnlyTransactional; import com.everyonewaiter.domain.menu.Category; import com.everyonewaiter.domain.menu.CategoryView; import java.util.List; import lombok.RequiredArgsConstructor; -import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -26,7 +24,6 @@ public List findAll(Long storeId) { @Override @Transactional(readOnly = true) - @Cacheable(cacheNames = CacheName.STORE_MENU, key = "#storeId", condition = "#storeId != null") public CategoryView.CategoryDetails findAllView(Long storeId) { return CategoryView.CategoryDetails.from( categoryRepository.findAll(storeId).stream() diff --git a/src/main/java/com/everyonewaiter/application/menu/MenuModifyService.java b/src/main/java/com/everyonewaiter/application/menu/MenuModifyService.java index b3fb10be..0ed8fcb6 100644 --- a/src/main/java/com/everyonewaiter/application/menu/MenuModifyService.java +++ b/src/main/java/com/everyonewaiter/application/menu/MenuModifyService.java @@ -8,7 +8,6 @@ import com.everyonewaiter.application.menu.provided.MenuFinder; import com.everyonewaiter.application.menu.provided.MenuManager; import com.everyonewaiter.application.menu.required.MenuRepository; -import com.everyonewaiter.application.support.CacheName; import com.everyonewaiter.application.support.DistributedLock; import com.everyonewaiter.domain.menu.Category; import com.everyonewaiter.domain.menu.ExceedMaxMenuCountException; @@ -22,7 +21,6 @@ import com.everyonewaiter.domain.sse.SseEvent; import java.util.List; import lombok.RequiredArgsConstructor; -import org.springframework.cache.annotation.CacheEvict; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -43,7 +41,6 @@ class MenuModifyService implements MenuManager { @Override @DistributedLock(key = "#storeId + '-menu'") - @CacheEvict(cacheNames = CacheName.STORE_MENU, key = "#storeId") public Menu create( Long categoryId, Long storeId, @@ -75,7 +72,6 @@ private void validateMenuCreate(Long categoryId) { @Override @DistributedLock(key = "#storeId + '-menu'") - @CacheEvict(cacheNames = CacheName.STORE_MENU, key = "#storeId") public Menu update(Long menuId, Long storeId, MenuUpdateRequest updateRequest) { Menu menu = menuFinder.findOrThrow(menuId, storeId); @@ -86,7 +82,6 @@ public Menu update(Long menuId, Long storeId, MenuUpdateRequest updateRequest) { @Override @DistributedLock(key = "#storeId + '-menu'") - @CacheEvict(cacheNames = CacheName.STORE_MENU, key = "#storeId") public Menu update( Long menuId, Long storeId, @@ -102,7 +97,6 @@ public Menu update( @Override @DistributedLock(key = "#storeId + '-menu'") - @CacheEvict(cacheNames = CacheName.STORE_MENU, key = "#storeId") public Menu movePosition( Long sourceId, Long targetId, @@ -122,7 +116,6 @@ public Menu movePosition( @Override @DistributedLock(key = "#storeId + '-menu'") - @CacheEvict(cacheNames = CacheName.STORE_MENU, key = "#storeId") public void delete(Long menuId, Long storeId, Long categoryId) { Menu menu = menuFinder.findOrThrow(menuId, storeId, categoryId); @@ -133,7 +126,6 @@ public void delete(Long menuId, Long storeId, Long categoryId) { @Override @DistributedLock(key = "#storeId + '-menu'") - @CacheEvict(cacheNames = CacheName.STORE_MENU, key = "#storeId") public void deleteAll(Long storeId, MenuDeleteRequest deleteRequest) { List menus = menuFinder.findAll(storeId, deleteRequest.menuIds()); diff --git a/src/main/java/com/everyonewaiter/application/support/CacheName.java b/src/main/java/com/everyonewaiter/application/support/CacheName.java deleted file mode 100644 index 9045da83..00000000 --- a/src/main/java/com/everyonewaiter/application/support/CacheName.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.everyonewaiter.application.support; - -import static lombok.AccessLevel.PRIVATE; - -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = PRIVATE) -public final class CacheName { - - public static final String STORE_MENU = "storeMenu"; - -} From 6403ef5ed9315e1e055b4825d8cca20f7654dedd Mon Sep 17 00:00:00 2001 From: handwoong Date: Wed, 31 Dec 2025 22:27:15 +0900 Subject: [PATCH 4/6] =?UTF-8?q?fix:=20=EC=A3=BC=EB=B0=A9=20=EB=B9=8C?= =?UTF-8?q?=EC=A7=80=20=EB=AF=B8=EC=B6=9C=EB=A0=A5=20=EB=A9=94=EB=89=B4=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/receipt/ReceiptCreateService.java | 3 ++- .../application/receipt/provided/ReceiptCreator.java | 2 ++ src/main/java/com/everyonewaiter/domain/pos/PosTable.java | 7 +++++-- .../java/com/everyonewaiter/domain/receipt/Receipt.java | 8 ++++---- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/everyonewaiter/application/receipt/ReceiptCreateService.java b/src/main/java/com/everyonewaiter/application/receipt/ReceiptCreateService.java index b260c7db..5bc93e4f 100644 --- a/src/main/java/com/everyonewaiter/application/receipt/ReceiptCreateService.java +++ b/src/main/java/com/everyonewaiter/application/receipt/ReceiptCreateService.java @@ -6,6 +6,7 @@ import com.everyonewaiter.domain.order.Order; import com.everyonewaiter.domain.order.OrderUpdateRequests; import com.everyonewaiter.domain.receipt.Receipt; +import jakarta.annotation.Nullable; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -42,7 +43,7 @@ public Receipt create(Long storeId, int tableNo, List orderIds) { @Override @Transactional(readOnly = true) - public Receipt createDiff( + public @Nullable Receipt createDiff( Long storeId, int tableNo, List orders, diff --git a/src/main/java/com/everyonewaiter/application/receipt/provided/ReceiptCreator.java b/src/main/java/com/everyonewaiter/application/receipt/provided/ReceiptCreator.java index 812809cc..892231ef 100644 --- a/src/main/java/com/everyonewaiter/application/receipt/provided/ReceiptCreator.java +++ b/src/main/java/com/everyonewaiter/application/receipt/provided/ReceiptCreator.java @@ -3,6 +3,7 @@ import com.everyonewaiter.domain.order.Order; import com.everyonewaiter.domain.order.OrderUpdateRequests; import com.everyonewaiter.domain.receipt.Receipt; +import jakarta.annotation.Nullable; import jakarta.validation.Valid; import java.util.List; @@ -12,6 +13,7 @@ public interface ReceiptCreator { Receipt create(Long storeId, int tableNo, List orderIds); + @Nullable Receipt createDiff( Long storeId, int tableNo, diff --git a/src/main/java/com/everyonewaiter/domain/pos/PosTable.java b/src/main/java/com/everyonewaiter/domain/pos/PosTable.java index da26a95d..40208157 100644 --- a/src/main/java/com/everyonewaiter/domain/pos/PosTable.java +++ b/src/main/java/com/everyonewaiter/domain/pos/PosTable.java @@ -18,6 +18,7 @@ import com.everyonewaiter.domain.receipt.ReceiptResendEvent; import com.everyonewaiter.domain.sse.SseEvent; import com.everyonewaiter.domain.store.Store; +import jakarta.annotation.Nullable; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; @@ -127,14 +128,16 @@ public void cancelOrder(Long orderId) { registerEvent(new SseEvent(store.getId(), POS, UPDATE, getTableNo())); } - public void updateOrder(OrderUpdateRequests updateRequests, Receipt diff) { + public void updateOrder(OrderUpdateRequests updateRequests, @Nullable Receipt diff) { PosTableActivity posTableActivity = getActiveActivityOrThrow(); for (OrderUpdateRequest updateRequest : updateRequests.orders()) { posTableActivity.updateOrder(updateRequest); } - registerEvent(new OrderUpdateEvent(store.getId(), tableNo, diff)); + if (diff != null) { + registerEvent(new OrderUpdateEvent(store.getId(), tableNo, diff)); + } registerEvent(new SseEvent(store.getId(), ORDER, UPDATE, getTableNo())); registerEvent(new SseEvent(store.getId(), POS, UPDATE, getTableNo())); } diff --git a/src/main/java/com/everyonewaiter/domain/receipt/Receipt.java b/src/main/java/com/everyonewaiter/domain/receipt/Receipt.java index a4308028..3b67574a 100644 --- a/src/main/java/com/everyonewaiter/domain/receipt/Receipt.java +++ b/src/main/java/com/everyonewaiter/domain/receipt/Receipt.java @@ -2,9 +2,9 @@ import com.everyonewaiter.domain.order.Order; import com.everyonewaiter.domain.order.OrderMenu; -import com.everyonewaiter.domain.order.OrderMenuNotFoundException; import com.everyonewaiter.domain.order.OrderMenuQuantityUpdateRequest; import com.everyonewaiter.domain.order.OrderUpdateRequests; +import jakarta.annotation.Nullable; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -36,7 +36,7 @@ public static Receipt of(int tableNo, List orders, int printNo) { ); } - public static Receipt diff( + public static @Nullable Receipt diff( int tableNo, List orders, OrderUpdateRequests updateRequests, @@ -54,7 +54,7 @@ public static Receipt diff( List receiptMenus = new ArrayList<>(); for (OrderMenuQuantityUpdateRequest afterOrderMenu : afterOrderMenus) { if (!beforeOrderMenus.containsKey(afterOrderMenu.orderMenuId())) { - throw new OrderMenuNotFoundException(); + continue; } OrderMenu orderMenu = beforeOrderMenus.get(afterOrderMenu.orderMenuId()); @@ -68,7 +68,7 @@ public static Receipt diff( } } - return new Receipt(tableNo, "", printNo, receiptMenus); + return receiptMenus.isEmpty() ? null : new Receipt(tableNo, "", printNo, receiptMenus); } public static Receipt cancel(int tableNo, Order order, int printNo) { From ef36e54a5ceb45ef211e393677e3ca304ff519d1 Mon Sep 17 00:00:00 2001 From: handwoong Date: Wed, 31 Dec 2025 22:31:44 +0900 Subject: [PATCH 5/6] =?UTF-8?q?chore:=20=EB=B2=84=EC=A0=84=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 2 +- gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index a0e5137e..ecf8fda1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ services: everyonewaiter-api: container_name: everyonewaiter-api build: . - image: everyonewaiter-api:1.0.7 + image: everyonewaiter-api:1.0.8 ports: - "8081:8081" volumes: diff --git a/gradle.properties b/gradle.properties index 1df2bfa5..1dad7f4b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # Artifact appGroup=com.everyonewaiter -appVersion=1.0.7 +appVersion=1.0.8 appDescription=모두의 웨이터 API # Plugin From 873ea72c063f46196956f77f0300719b65f41ac5 Mon Sep 17 00:00:00 2001 From: handwoong Date: Thu, 1 Jan 2026 00:24:07 +0900 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20=EB=A7=A4=EC=B6=9C=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=9D=91=EB=8B=B5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/pos/PosTableActivityQueryService.java | 1 - src/main/java/com/everyonewaiter/domain/pos/PosView.java | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/everyonewaiter/application/pos/PosTableActivityQueryService.java b/src/main/java/com/everyonewaiter/application/pos/PosTableActivityQueryService.java index 13c14c20..880062d8 100644 --- a/src/main/java/com/everyonewaiter/application/pos/PosTableActivityQueryService.java +++ b/src/main/java/com/everyonewaiter/application/pos/PosTableActivityQueryService.java @@ -28,7 +28,6 @@ class PosTableActivityQueryService implements PosTableActivityFinder { public PosView.Revenue getRevenue(Long storeId, Instant start, Instant end) { return PosView.Revenue.from( posTableActivityRepository.getOrderRevenue(storeId, start, end, OrderState.ORDER), - posTableActivityRepository.getOrderRevenue(storeId, start, end, OrderState.CANCEL), posTableActivityRepository.getDiscountRevenue(storeId, start, end), posTableActivityRepository.getPaymentRevenue(storeId, start, end, CASH, APPROVE), posTableActivityRepository.getPaymentRevenue(storeId, start, end, CARD, APPROVE), diff --git a/src/main/java/com/everyonewaiter/domain/pos/PosView.java b/src/main/java/com/everyonewaiter/domain/pos/PosView.java index 8198c8cc..a9f0dd8e 100644 --- a/src/main/java/com/everyonewaiter/domain/pos/PosView.java +++ b/src/main/java/com/everyonewaiter/domain/pos/PosView.java @@ -40,7 +40,6 @@ public record Revenue( public static Revenue from( long totalOrderedOrderPrice, - long totalCanceledOrderPrice, long totalDiscountPrice, long cashPaymentApprovePrice, long cardPaymentApprovePrice, @@ -51,7 +50,7 @@ public static Revenue from( long totalPaymentCancelPrice = cashPaymentCancelPrice + cardPaymentCancelPrice; return new Revenue( - totalOrderedOrderPrice - totalCanceledOrderPrice, + totalOrderedOrderPrice, totalDiscountPrice, totalPaymentApprovePrice - totalPaymentCancelPrice, cashPaymentApprovePrice,