From 35c09567e54ebb7dc6316ab8518090a527af4b11 Mon Sep 17 00:00:00 2001 From: woosung1223 Date: Wed, 15 Nov 2023 21:54:10 +0900 Subject: [PATCH 1/5] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20`@SpringBootTest`=20=EC=B6=94=EA=B0=80=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/auth/AuthArgumentResolverTest.java | 18 +++++++++++------- .../backend/auth/AuthInterceptorTest.java | 14 +++++++++++--- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/backend/src/test/java/harustudy/backend/auth/AuthArgumentResolverTest.java b/backend/src/test/java/harustudy/backend/auth/AuthArgumentResolverTest.java index bcc70182..f0392b28 100644 --- a/backend/src/test/java/harustudy/backend/auth/AuthArgumentResolverTest.java +++ b/backend/src/test/java/harustudy/backend/auth/AuthArgumentResolverTest.java @@ -6,13 +6,14 @@ import harustudy.backend.auth.dto.AuthMember; import harustudy.backend.auth.service.AuthService; +import harustudy.backend.auth.util.BearerAuthorizationParser; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; import org.mockito.Mock; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.core.MethodParameter; import org.springframework.http.HttpHeaders; import org.springframework.mock.web.MockHttpServletRequest; @@ -23,14 +24,15 @@ @SuppressWarnings("NonAsciiCharacters") @DisplayNameGeneration(ReplaceUnderscores.class) -@SpringBootTest +@ExtendWith(MockitoExtension.class) class AuthArgumentResolverTest { - @Autowired + @InjectMocks private AuthArgumentResolver authArgumentResolver; - - @MockBean + @Mock private AuthService authService; + @Mock + private BearerAuthorizationParser bearerAuthorizationParser; @Mock private MethodParameter methodParameter; @@ -48,6 +50,8 @@ class AuthArgumentResolverTest { request.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken); NativeWebRequest nativeWebRequest = new ServletWebRequest(request); + given(bearerAuthorizationParser.parse(any(String.class))) + .willReturn(accessToken); given(authService.parseMemberId(any(String.class))) .willReturn(mockedAuthMemberId); diff --git a/backend/src/test/java/harustudy/backend/auth/AuthInterceptorTest.java b/backend/src/test/java/harustudy/backend/auth/AuthInterceptorTest.java index 9f1b428f..c20f48eb 100644 --- a/backend/src/test/java/harustudy/backend/auth/AuthInterceptorTest.java +++ b/backend/src/test/java/harustudy/backend/auth/AuthInterceptorTest.java @@ -7,9 +7,15 @@ import static org.mockito.Mockito.times; import harustudy.backend.auth.service.AuthService; +import harustudy.backend.auth.util.BearerAuthorizationParser; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -19,14 +25,16 @@ @SuppressWarnings("NonAsciiCharacters") @DisplayNameGeneration(ReplaceUnderscores.class) -@SpringBootTest +@ExtendWith(MockitoExtension.class) class AuthInterceptorTest { - @Autowired + @InjectMocks private AuthInterceptor authInterceptor; - @MockBean + @Mock private AuthService authService; + @Spy + private BearerAuthorizationParser bearerAuthorizationParser = new BearerAuthorizationParser(); @Test void preflight_요청시_예외를_던지지_않는다() { From 70f8b6865b4158316cf5d8e1298e08c7b1d2f476 Mon Sep 17 00:00:00 2001 From: woosung1223 Date: Wed, 15 Nov 2023 23:15:03 +0900 Subject: [PATCH 2/5] =?UTF-8?q?refactor:=20DI=EB=A5=BC=20=ED=86=B5?= =?UTF-8?q?=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=86=8D=EB=8F=84=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/auth/util/JwtTokenProvider.java | 5 +++- .../harustudy/backend/config/BeanConfig.java | 7 +++++ .../integration/AuthIntegrationTest.java | 24 ++++++++------- .../backend/integration/IntegrationTest.java | 29 ++++++++++--------- 4 files changed, 39 insertions(+), 26 deletions(-) diff --git a/backend/src/main/java/harustudy/backend/auth/util/JwtTokenProvider.java b/backend/src/main/java/harustudy/backend/auth/util/JwtTokenProvider.java index 99281506..ee6bbee2 100644 --- a/backend/src/main/java/harustudy/backend/auth/util/JwtTokenProvider.java +++ b/backend/src/main/java/harustudy/backend/auth/util/JwtTokenProvider.java @@ -1,6 +1,7 @@ package harustudy.backend.auth.util; import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Clock; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.security.Keys; @@ -14,6 +15,8 @@ @Component public class JwtTokenProvider { + private final Clock clock; + @Builder public String createAccessToken(String subject, Long accessTokenExpireLength, String secretKey) { Claims claims = generateClaims(subject, accessTokenExpireLength); @@ -28,7 +31,7 @@ public String createAccessToken(String subject, Long accessTokenExpireLength, St } private Claims generateClaims(String subject, Long accessTokenExpireLength) { - Date now = new Date(); + Date now = clock.now(); Date expiredAt = new Date(now.getTime() + accessTokenExpireLength); return Jwts.claims() diff --git a/backend/src/main/java/harustudy/backend/config/BeanConfig.java b/backend/src/main/java/harustudy/backend/config/BeanConfig.java index d1ec9568..a24644e8 100644 --- a/backend/src/main/java/harustudy/backend/config/BeanConfig.java +++ b/backend/src/main/java/harustudy/backend/config/BeanConfig.java @@ -2,6 +2,8 @@ import harustudy.backend.participantcode.domain.CodeGenerationStrategy; import harustudy.backend.participantcode.domain.GenerationStrategy; +import io.jsonwebtoken.Clock; +import io.jsonwebtoken.impl.DefaultClock; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -12,4 +14,9 @@ public class BeanConfig { public GenerationStrategy generationStrategy() { return new CodeGenerationStrategy(); } + + @Bean + public Clock clock() { + return new DefaultClock(); + } } diff --git a/backend/src/test/java/harustudy/backend/integration/AuthIntegrationTest.java b/backend/src/test/java/harustudy/backend/integration/AuthIntegrationTest.java index 97190a33..eeb44e8e 100644 --- a/backend/src/test/java/harustudy/backend/integration/AuthIntegrationTest.java +++ b/backend/src/test/java/harustudy/backend/integration/AuthIntegrationTest.java @@ -1,26 +1,27 @@ package harustudy.backend.integration; +import static org.assertj.core.api.SoftAssertions.assertSoftly; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + import harustudy.backend.auth.domain.RefreshToken; import harustudy.backend.auth.dto.OauthLoginRequest; import harustudy.backend.auth.dto.OauthTokenResponse; import harustudy.backend.auth.dto.TokenResponse; import harustudy.backend.member.domain.Member; import jakarta.servlet.http.Cookie; -import org.junit.jupiter.api.BeforeEach; +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.Map; import org.junit.jupiter.api.Test; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.web.servlet.MvcResult; -import java.nio.charset.StandardCharsets; -import java.util.Map; - -import static org.assertj.core.api.SoftAssertions.assertSoftly; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @SuppressWarnings("NonAsciiCharacters") class AuthIntegrationTest extends IntegrationTest { @@ -65,7 +66,8 @@ class AuthIntegrationTest extends IntegrationTest { // access token을 재발급 하더라도 Date는 초 단위의 시간 정보를 담은 액세스 토큰을 생성하기 때문에 // 같은 access token이 만들어지는 문제가 있어서 갱신된다는 것을 검증하기 위해 사용 - Thread.sleep(1000); + Date now = new Date(); + when(customClock.now()).thenReturn(new Date(now.getTime() + 1000L)); // when MvcResult result = mockMvc.perform( diff --git a/backend/src/test/java/harustudy/backend/integration/IntegrationTest.java b/backend/src/test/java/harustudy/backend/integration/IntegrationTest.java index 7f63f4b8..f7eb8464 100644 --- a/backend/src/test/java/harustudy/backend/integration/IntegrationTest.java +++ b/backend/src/test/java/harustudy/backend/integration/IntegrationTest.java @@ -1,37 +1,29 @@ package harustudy.backend.integration; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.mockito.Mockito.when; import com.fasterxml.jackson.databind.ObjectMapper; import harustudy.backend.auth.config.TokenConfig; import harustudy.backend.auth.domain.RefreshToken; import harustudy.backend.auth.domain.oauth.OauthClients; -import harustudy.backend.auth.dto.OauthLoginRequest; -import harustudy.backend.auth.dto.OauthTokenResponse; -import harustudy.backend.auth.dto.TokenResponse; import harustudy.backend.auth.util.JwtTokenProvider; import harustudy.backend.member.domain.LoginType; import harustudy.backend.member.domain.Member; import harustudy.backend.participantcode.domain.GenerationStrategy; +import io.jsonwebtoken.Clock; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import jakarta.servlet.http.Cookie; -import java.nio.charset.StandardCharsets; -import java.util.Map; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.MvcResult; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.context.WebApplicationContext; +import java.util.Date; @DisplayNameGeneration(ReplaceUnderscores.class) @@ -55,14 +47,23 @@ class IntegrationTest { @Autowired private TokenConfig tokenConfig; + @MockBean + protected OauthClients oauthClients; + + @MockBean + protected Clock customClock; + @Autowired protected GenerationStrategy generationStrategy; - @MockBean - protected OauthClients oauthClients; + @BeforeEach + void setUp() { + when(customClock.now()).thenReturn(new Date()); + } protected MemberDto createMember(String name) { Member member = generateAndSaveMemberNamedWith(name); + when(customClock.now()).thenReturn(new Date()); String accessToken = jwtTokenProvider.createAccessToken(String.valueOf(member.getId()), tokenConfig.accessTokenExpireLength(), tokenConfig.secretKey()); RefreshToken refreshToken = generateAndSaveRefreshTokenOf(member); From f87997e482bb8f5604b9a1629a9875b294787a20 Mon Sep 17 00:00:00 2001 From: woosung1223 Date: Wed, 15 Nov 2023 23:15:15 +0900 Subject: [PATCH 3/5] =?UTF-8?q?chore:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=BB=A8=ED=85=8D=EC=8A=A4=ED=8A=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../harustudy/backend/HaruStudyApplicationTests.java | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 backend/src/test/java/harustudy/backend/HaruStudyApplicationTests.java diff --git a/backend/src/test/java/harustudy/backend/HaruStudyApplicationTests.java b/backend/src/test/java/harustudy/backend/HaruStudyApplicationTests.java deleted file mode 100644 index 4a513b3a..00000000 --- a/backend/src/test/java/harustudy/backend/HaruStudyApplicationTests.java +++ /dev/null @@ -1,12 +0,0 @@ -package harustudy.backend; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class HaruStudyApplicationTests { - - @Test - void contextLoads() { - } -} From c0c79523e03fe4f1312ae9850e2623c660297bf6 Mon Sep 17 00:00:00 2001 From: woosung1223 Date: Thu, 16 Nov 2023 00:32:53 +0900 Subject: [PATCH 4/5] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20Mocking=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/auth/AuthArgumentResolverTest.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/backend/src/test/java/harustudy/backend/auth/AuthArgumentResolverTest.java b/backend/src/test/java/harustudy/backend/auth/AuthArgumentResolverTest.java index f0392b28..793c6069 100644 --- a/backend/src/test/java/harustudy/backend/auth/AuthArgumentResolverTest.java +++ b/backend/src/test/java/harustudy/backend/auth/AuthArgumentResolverTest.java @@ -34,13 +34,6 @@ class AuthArgumentResolverTest { @Mock private BearerAuthorizationParser bearerAuthorizationParser; - @Mock - private MethodParameter methodParameter; - @Mock - private ModelAndViewContainer modelAndViewContainer; - @Mock - private WebDataBinderFactory webDataBinderFactory; - @Test void 액세스_토큰의_파싱된_아이디에_해당하는_인증_멤버가_반환된다() { // given @@ -56,8 +49,7 @@ class AuthArgumentResolverTest { .willReturn(mockedAuthMemberId); // when - AuthMember authMember = authArgumentResolver.resolveArgument(methodParameter, - modelAndViewContainer, nativeWebRequest, webDataBinderFactory); + AuthMember authMember = authArgumentResolver.resolveArgument(null, null, nativeWebRequest, null); // then assertThat(authMember.id()).isEqualTo(Long.valueOf(mockedAuthMemberId)); From 2cfe9ff5ee1443d7bcf4c9e149a640d3e28a09cc Mon Sep 17 00:00:00 2001 From: woosung1223 Date: Thu, 16 Nov 2023 00:40:43 +0900 Subject: [PATCH 5/5] =?UTF-8?q?chore:=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/harustudy/backend/integration/AuthIntegrationTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/backend/src/test/java/harustudy/backend/integration/AuthIntegrationTest.java b/backend/src/test/java/harustudy/backend/integration/AuthIntegrationTest.java index eeb44e8e..a32790e2 100644 --- a/backend/src/test/java/harustudy/backend/integration/AuthIntegrationTest.java +++ b/backend/src/test/java/harustudy/backend/integration/AuthIntegrationTest.java @@ -64,8 +64,6 @@ class AuthIntegrationTest extends IntegrationTest { // given MemberDto memberDto = createMember("member1"); - // access token을 재발급 하더라도 Date는 초 단위의 시간 정보를 담은 액세스 토큰을 생성하기 때문에 - // 같은 access token이 만들어지는 문제가 있어서 갱신된다는 것을 검증하기 위해 사용 Date now = new Date(); when(customClock.now()).thenReturn(new Date(now.getTime() + 1000L));