diff --git a/src/main/java/org/runimo/runimo/auth/service/SignUpUsecaseImpl.java b/src/main/java/org/runimo/runimo/auth/service/SignUpUsecaseImpl.java index cf352570..fbc05f73 100644 --- a/src/main/java/org/runimo/runimo/auth/service/SignUpUsecaseImpl.java +++ b/src/main/java/org/runimo/runimo/auth/service/SignUpUsecaseImpl.java @@ -11,6 +11,8 @@ import org.runimo.runimo.auth.service.dto.SignupUserResponse; import org.runimo.runimo.auth.service.dto.UserSignupCommand; import org.runimo.runimo.external.FileStorageService; +import org.runimo.runimo.item.domain.Egg; +import org.runimo.runimo.rewards.service.eggs.EggGrantService; import org.runimo.runimo.user.domain.AppleUserToken; import org.runimo.runimo.user.domain.SocialProvider; import org.runimo.runimo.user.domain.User; @@ -28,6 +30,7 @@ public class SignUpUsecaseImpl implements SignUpUsecase { private static final int REGISTER_CUTOFF_MIN = 10; private final UserRegisterService userRegisterService; private final FileStorageService fileStorageService; + private final EggGrantService eggGrantService; private final JwtTokenFactory jwtTokenFactory; private final SignupTokenRepository signupTokenRepository; private final AppleUserTokenRepository appleUserTokenRepository; @@ -50,8 +53,11 @@ public SignupUserResponse register(UserSignupCommand command) { if (payload.socialProvider() == SocialProvider.APPLE) { createAppleUserToken(savedUser.getId(), signupToken); } + Egg grantedEgg = eggGrantService.grantGreetingEggToUser(savedUser); + removeSignupToken(payload.token()); - return new SignupUserResponse(savedUser, jwtTokenFactory.generateTokenPair(savedUser)); + return new SignupUserResponse(savedUser, jwtTokenFactory.generateTokenPair(savedUser), + grantedEgg); } private void removeSignupToken(String token) { diff --git a/src/main/java/org/runimo/runimo/auth/service/dto/SignupUserResponse.java b/src/main/java/org/runimo/runimo/auth/service/dto/SignupUserResponse.java index fe3c0990..011ade89 100644 --- a/src/main/java/org/runimo/runimo/auth/service/dto/SignupUserResponse.java +++ b/src/main/java/org/runimo/runimo/auth/service/dto/SignupUserResponse.java @@ -1,18 +1,26 @@ package org.runimo.runimo.auth.service.dto; +import org.runimo.runimo.item.domain.Egg; import org.runimo.runimo.user.domain.User; public record SignupUserResponse( Long userId, String nickname, String imgUrl, - TokenPair tokenPair + TokenPair tokenPair, + String greetingEggName, + String greetingEggType, + String greetingEggImgUrl ) { - public SignupUserResponse(final User user, final TokenPair tokenPair) { + public SignupUserResponse(final User user, final TokenPair tokenPair, final Egg greetingEgg) { this(user.getId(), user.getNickname(), user.getImgUrl(), - tokenPair); + tokenPair, + greetingEgg.getName(), + greetingEgg.getEggType().getName(), + greetingEgg.getImgUrl() + ); } } diff --git a/src/main/java/org/runimo/runimo/rewards/service/eggs/EggGrantService.java b/src/main/java/org/runimo/runimo/rewards/service/eggs/EggGrantService.java index fb70d3ab..72d86d33 100644 --- a/src/main/java/org/runimo/runimo/rewards/service/eggs/EggGrantService.java +++ b/src/main/java/org/runimo/runimo/rewards/service/eggs/EggGrantService.java @@ -23,12 +23,13 @@ public class EggGrantService { private final EggTypeRepository eggTypeRepository; @Transactional - public void grantGreetingEggToUser(User user) { + public Egg grantGreetingEggToUser(User user) { if (!user.checkUserFirstRun()) { - return; + return Egg.EMPTY; } Egg grantedEgg = eggFactory.createGreetingEgg(); userItemProcessor.updateItemQuantity(user.getId(), grantedEgg.getId(), GREETING_EGG_AMOUNT); + return grantedEgg; } @Transactional diff --git a/src/main/java/org/runimo/runimo/user/service/UserRegisterService.java b/src/main/java/org/runimo/runimo/user/service/UserRegisterService.java index 0951fe6b..d3bdd596 100644 --- a/src/main/java/org/runimo/runimo/user/service/UserRegisterService.java +++ b/src/main/java/org/runimo/runimo/user/service/UserRegisterService.java @@ -2,7 +2,6 @@ import lombok.RequiredArgsConstructor; import org.runimo.runimo.auth.exceptions.SignUpException; -import org.runimo.runimo.rewards.service.eggs.EggGrantService; import org.runimo.runimo.user.domain.SocialProvider; import org.runimo.runimo.user.domain.User; import org.runimo.runimo.user.enums.UserHttpResponseCode; @@ -18,7 +17,6 @@ public class UserRegisterService { private final UserCreator userCreator; private final UserItemCreator userItemCreator; - private final EggGrantService eggGrantService; private final OAuthInfoRepository oAuthInfoRepository; @Transactional @@ -28,13 +26,12 @@ public User registerUser(UserRegisterCommand command) { userCreator.createUserOAuthInfo(savedUser, command.socialProvider(), command.providerId()); userCreator.createLovePoint(savedUser.getId()); userItemCreator.createAll(savedUser.getId()); - eggGrantService.grantGreetingEggToUser(savedUser); return savedUser; } public void validateExistingUser(String providerId, SocialProvider socialProvider) { - if(oAuthInfoRepository.existsByProviderIdAndProvider( - providerId, socialProvider)) { + if (oAuthInfoRepository.existsByProviderIdAndProvider( + providerId, socialProvider)) { throw new SignUpException(UserHttpResponseCode.SIGNIN_FAIL_ALREADY_EXIST); } } diff --git a/src/test/java/org/runimo/runimo/auth/service/SignUpUsecaseTest.java b/src/test/java/org/runimo/runimo/auth/service/SignUpUsecaseTest.java index 4bd64803..fdb80bef 100644 --- a/src/test/java/org/runimo/runimo/auth/service/SignUpUsecaseTest.java +++ b/src/test/java/org/runimo/runimo/auth/service/SignUpUsecaseTest.java @@ -1,5 +1,7 @@ package org.runimo.runimo.auth.service; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -17,8 +19,12 @@ import org.runimo.runimo.auth.jwt.JwtTokenFactory; import org.runimo.runimo.auth.jwt.SignupTokenPayload; import org.runimo.runimo.auth.repository.SignupTokenRepository; +import org.runimo.runimo.auth.service.dto.SignupUserResponse; import org.runimo.runimo.auth.service.dto.UserSignupCommand; import org.runimo.runimo.external.FileStorageService; +import org.runimo.runimo.item.EggFixtures; +import org.runimo.runimo.rewards.service.eggs.EggGrantService; +import org.runimo.runimo.user.UserFixtures; import org.runimo.runimo.user.domain.Gender; import org.runimo.runimo.user.domain.SocialProvider; import org.runimo.runimo.user.enums.UserHttpResponseCode; @@ -27,53 +33,84 @@ class SignUpUsecaseTest { - @Mock - private UserRegisterService userRegisterService; - @Mock - private FileStorageService fileStorageService; - @Mock - private JwtTokenFactory jwtTokenFactory; - @Mock - private SignupTokenRepository signupTokenRepository; - @Mock - private AppleUserTokenRepository appleUserTokenRepository; - @Mock - private JwtResolver jwtResolver; + @Mock + private UserRegisterService userRegisterService; + @Mock + private FileStorageService fileStorageService; + @Mock + private EggGrantService eggGrantService; + @Mock + private JwtTokenFactory jwtTokenFactory; + @Mock + private SignupTokenRepository signupTokenRepository; + @Mock + private AppleUserTokenRepository appleUserTokenRepository; + @Mock + private JwtResolver jwtResolver; - private SignUpUsecase sut; + private SignUpUsecase sut; - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - sut = new SignUpUsecaseImpl( - userRegisterService, - fileStorageService, - jwtTokenFactory, - signupTokenRepository, - appleUserTokenRepository, - jwtResolver - ); - } + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + sut = new SignUpUsecaseImpl( + userRegisterService, + fileStorageService, + eggGrantService, + jwtTokenFactory, + signupTokenRepository, + appleUserTokenRepository, + jwtResolver + ); + } - @Test - void 유저가_이미_존재하면_실패() { - // given - String registerToken = "dummy.token.value"; - SignupTokenPayload payload = new SignupTokenPayload(registerToken, "socialId123", - SocialProvider.KAKAO); + @Test + void 회원가입_시_환영_알_지급() { + // given + String registerToken = "dummy.token.value"; + SignupTokenPayload payload = new SignupTokenPayload(registerToken, "socialId123", + SocialProvider.KAKAO); - when(jwtResolver.getSignupTokenPayload(registerToken)).thenReturn(payload); - when(signupTokenRepository.findByIdAndCreatedAtAfter(eq(registerToken), any())) - .thenReturn(Optional.of(new SignupToken( - registerToken, "refresh", "refresh", SocialProvider.KAKAO))); + when(jwtResolver.getSignupTokenPayload(registerToken)).thenReturn(payload); + when(signupTokenRepository.findByIdAndCreatedAtAfter(eq(registerToken), any())) + .thenReturn(Optional.of(new SignupToken( + registerToken, "refresh", "refresh", SocialProvider.KAKAO))); + when(userRegisterService.registerUser(any())).thenReturn(UserFixtures.getUserWithId(1L)); + when(eggGrantService.grantGreetingEggToUser(any())).thenReturn( + EggFixtures.createDefaultEgg()); + when(jwtTokenFactory.generateTokenPair(any())).thenReturn(UserFixtures.TEST_TOKEN_PAIR); - doThrow(new org.runimo.runimo.auth.exceptions.SignUpException( - UserHttpResponseCode.SIGNIN_FAIL_ALREADY_EXIST)) - .when(userRegisterService) - .validateExistingUser(payload.providerId(), payload.socialProvider()); + SignupUserResponse response = sut + .register(new UserSignupCommand(registerToken, "nickname", null, Gender.UNKNOWN)); - assertThrows(SignUpException.class, () -> { - sut.register(new UserSignupCommand(registerToken, "nickname", null, Gender.UNKNOWN)); - }); - } + assertEquals(1L, response.userId()); + assertEquals(UserFixtures.TEST_USER_NICKNAME, response.nickname()); + assertEquals(UserFixtures.TEST_USER_IMG_URL, response.imgUrl()); + assertNotNull(response.tokenPair()); + assertEquals(EggFixtures.TEST_EGG_NAME, response.greetingEggName()); + assertEquals(EggFixtures.TEST_EGG_TYPE_NAME, response.greetingEggType()); + assertEquals(EggFixtures.TEST_EGG_IMG_URL, response.greetingEggImgUrl()); + } + + @Test + void 유저가_이미_존재하면_실패() { + // given + String registerToken = "dummy.token.value"; + SignupTokenPayload payload = new SignupTokenPayload(registerToken, "socialId123", + SocialProvider.KAKAO); + + when(jwtResolver.getSignupTokenPayload(registerToken)).thenReturn(payload); + when(signupTokenRepository.findByIdAndCreatedAtAfter(eq(registerToken), any())) + .thenReturn(Optional.of(new SignupToken( + registerToken, "refresh", "refresh", SocialProvider.KAKAO))); + + doThrow(new org.runimo.runimo.auth.exceptions.SignUpException( + UserHttpResponseCode.SIGNIN_FAIL_ALREADY_EXIST)) + .when(userRegisterService) + .validateExistingUser(payload.providerId(), payload.socialProvider()); + + assertThrows(SignUpException.class, () -> { + sut.register(new UserSignupCommand(registerToken, "nickname", null, Gender.UNKNOWN)); + }); + } } diff --git a/src/test/java/org/runimo/runimo/item/EggFixtures.java b/src/test/java/org/runimo/runimo/item/EggFixtures.java new file mode 100644 index 00000000..36678088 --- /dev/null +++ b/src/test/java/org/runimo/runimo/item/EggFixtures.java @@ -0,0 +1,51 @@ +package org.runimo.runimo.item; + +import org.runimo.runimo.item.domain.Egg; +import org.runimo.runimo.item.domain.EggType; + +public final class EggFixtures { + + public static final String TEST_EGG_CODE = "TEST_EGG"; + public static final String TEST_EGG_NAME = "Test Egg"; + public static final String TEST_EGG_DESCRIPTION = "A test egg for testing purposes"; + public static final String TEST_EGG_IMG_URL = "test_egg.png"; + + public static final String TEST_EGG_TYPE_NAME = "Test Type"; + public static final String TEST_EGG_TYPE_CODE = "TEST"; + public static final Long TEST_EGG_TYPE_DISTANCE = 1000L; + public static final Integer TEST_EGG_TYPE_LEVEL = 1; + + public static Egg createDefaultEgg() { + return Egg.builder() + .itemCode(TEST_EGG_CODE) + .name(TEST_EGG_NAME) + .description(TEST_EGG_DESCRIPTION) + .imgUrl(TEST_EGG_IMG_URL) + .eggType(createDefaultEggType()) + .hatchRequireAmount(10L) + .build(); + } + + public static Egg createCustomEgg(String itemCode, String name, String description, + String imgUrl, EggType eggType, Long hatchRequireAmount) { + return Egg.builder() + .itemCode(itemCode) + .name(name) + .description(description) + .imgUrl(imgUrl) + .eggType(eggType) + .hatchRequireAmount(hatchRequireAmount) + .build(); + } + + public static EggType createDefaultEggType() { + return EggType.of(TEST_EGG_TYPE_NAME, TEST_EGG_TYPE_CODE, TEST_EGG_TYPE_DISTANCE, + TEST_EGG_TYPE_LEVEL); + } + + public static EggType createCustomEggType(String name, String code, + Long requiredDistanceInMeters, Integer level) { + return EggType.of(name, code, requiredDistanceInMeters, level); + } + +} \ No newline at end of file diff --git a/src/test/java/org/runimo/runimo/user/UserFixtures.java b/src/test/java/org/runimo/runimo/user/UserFixtures.java index 1011b1d7..e2815be4 100644 --- a/src/test/java/org/runimo/runimo/user/UserFixtures.java +++ b/src/test/java/org/runimo/runimo/user/UserFixtures.java @@ -1,14 +1,21 @@ package org.runimo.runimo.user; +import org.runimo.runimo.auth.service.dto.TokenPair; import org.runimo.runimo.user.domain.User; import org.springframework.test.util.ReflectionTestUtils; public final class UserFixtures { + public static final String TEST_USER_NICKNAME = "test"; + public static final String TEST_USER_IMG_URL = "test"; + public static final TokenPair TEST_TOKEN_PAIR = new TokenPair( + "test-access-token-1", "test-refresh-token-1" + ); + public static User getDefaultUser() { return User.builder() - .nickname("test") - .imgUrl("test") + .nickname(TEST_USER_NICKNAME) + .imgUrl(TEST_USER_IMG_URL) .totalDistanceInMeters(0L) .totalTimeInSeconds(0L) .build(); @@ -16,8 +23,8 @@ public static User getDefaultUser() { public static User getUserWithId(Long id) { User user = User.builder() - .nickname("test") - .imgUrl("test") + .nickname(TEST_USER_NICKNAME) + .imgUrl(TEST_USER_IMG_URL) .totalDistanceInMeters(0L) .totalTimeInSeconds(0L) .build(); diff --git a/src/test/java/org/runimo/runimo/user/api/UserItemAcceptanceTest.java b/src/test/java/org/runimo/runimo/user/api/UserItemAcceptanceTest.java index 4aed0e56..7a3cff68 100644 --- a/src/test/java/org/runimo/runimo/user/api/UserItemAcceptanceTest.java +++ b/src/test/java/org/runimo/runimo/user/api/UserItemAcceptanceTest.java @@ -144,7 +144,10 @@ void tearDown() { 1L, "test-user", "https://test-image.com", - new TokenPair(token, "token2") + new TokenPair(token, "token2"), + "마당알", + "MADANG", + "test.url" )); AuthSignupRequest request = new AuthSignupRequest( diff --git a/src/test/java/org/runimo/runimo/user/service/usecases/UserRegisterServiceTest.java b/src/test/java/org/runimo/runimo/user/service/usecases/UserRegisterServiceTest.java index 343901b6..41ec5fbf 100644 --- a/src/test/java/org/runimo/runimo/user/service/usecases/UserRegisterServiceTest.java +++ b/src/test/java/org/runimo/runimo/user/service/usecases/UserRegisterServiceTest.java @@ -13,7 +13,6 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.runimo.runimo.rewards.service.eggs.EggGrantService; import org.runimo.runimo.user.domain.Gender; import org.runimo.runimo.user.domain.SocialProvider; import org.runimo.runimo.user.domain.User; @@ -30,9 +29,6 @@ class UserRegisterServiceTest { @Mock private UserItemCreator userItemCreator; - @Mock - private EggGrantService eggGrantService; - @InjectMocks private UserRegisterService userRegisterService; @@ -66,6 +62,5 @@ void setUp() { providerId); verify(userCreator, times(1)).createLovePoint(anyLong()); verify(userItemCreator, times(1)).createAll(anyLong()); - verify(eggGrantService, times(1)).grantGreetingEggToUser(mockUser); } }