Skip to content

Commit

Permalink
fix: ✏️ 엔티티 생성자 및 수정 메서드 유효성 검사 추가 (#111)
Browse files Browse the repository at this point in the history
* fix: 배포 파이프라인 이미지 빌드 버전 추가

* fix: device entity 생성자 유효성 검사

* fix: oauth entity 유효성 검사

* fix: oauth entity 생성자 deleted_at 제거

* fix: question entity 유효성 검사

* fix: querstion entity @sql_delete 옵션 추가

* fix: spending entity 유효성 검사

* fix: spending 카테고리 업데이트 메서드 제거

* fix: target_amount update 파라미터 타입 변환 래퍼 -> 원시타입

* fix: user entity 유효성 검사

* fix: user locked 타입 기본타입으로 수정 && get_locked() -> is_locked() 메서드로 수정

* fix: user update 메서드 유효성 검사 추가

* fix: notify_setting 필드 타입 기본타입으로 수정

* test: user_fixture notify_setting 필드 추가

* test: user 유효성 체크 실패로 인한 테스트 수정

* fix: spending 업데이트 시 entity 사용 -> 인자 받아서 처리

* test: spending user validation 체크로 인한 문제로 인한 테스트 수정

* test: 계정 연동 pre-condition 수정

* test: 로그인 비밀번호 불일치 시나리오 any() 로 given 수정

* test: domain 모듈 테스트에서 mock user 생성 시 유효성 만족하도록 수정

* fix: device entity 생성자 유효성 검사

* fix: oauth entity 유효성 검사

* fix: oauth entity 생성자 deleted_at 제거

* fix: question entity 유효성 검사

* fix: querstion entity @sql_delete 옵션 추가

* fix: spending entity 유효성 검사

* fix: spending 카테고리 업데이트 메서드 제거

* fix: target_amount update 파라미터 타입 변환 래퍼 -> 원시타입

* fix: user entity 유효성 검사

* fix: user locked 타입 기본타입으로 수정 && get_locked() -> is_locked() 메서드로 수정

* fix: user update 메서드 유효성 검사 추가

* fix: notify_setting 필드 타입 기본타입으로 수정

* test: user_fixture notify_setting 필드 추가

* test: user 유효성 체크 실패로 인한 테스트 수정

* fix: spending 업데이트 시 entity 사용 -> 인자 받아서 처리

* test: spending user validation 체크로 인한 문제로 인한 테스트 수정

* test: 계정 연동 pre-condition 수정

* test: 로그인 비밀번호 불일치 시나리오 any() 로 given 수정

* test: domain 모듈 테스트에서 mock user 생성 시 유효성 만족하도록 수정

* test: 최근 목표 금액 테스트 user 유효성 검사 반영
  • Loading branch information
psychology50 authored Jun 7, 2024
1 parent 079a61a commit 3453d88
Show file tree
Hide file tree
Showing 25 changed files with 197 additions and 175 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import kr.co.pennyway.api.common.validator.Password;
import kr.co.pennyway.domain.domains.user.domain.NotifySetting;
import kr.co.pennyway.domain.domains.user.domain.User;
import kr.co.pennyway.domain.domains.user.type.ProfileVisibility;
import kr.co.pennyway.domain.domains.user.type.Role;
Expand Down Expand Up @@ -31,6 +32,7 @@ public User toEntity(PasswordEncoder bCryptPasswordEncoder) {
.phone(phone)
.role(Role.USER)
.profileVisibility(ProfileVisibility.PUBLIC)
.notifySetting(NotifySetting.of(true, true, true))
.build();
}

Expand All @@ -49,6 +51,7 @@ public User toUser() {
.phone(phone)
.role(Role.USER)
.profileVisibility(ProfileVisibility.PUBLIC)
.notifySetting(NotifySetting.of(true, true, true))
.build();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,33 +69,6 @@ public Spending toEntity(User user, SpendingCustomCategory spendingCustomCategor
.build();
}

/**
* 지출 내역 수정시 사용되는 user필드가 null인 지출 내역으로 변환
*/
public Spending toEntity() {
return Spending.builder()
.amount(amount)
.category(icon)
.spendAt(spendAt.atStartOfDay())
.accountName(accountName)
.memo(memo)
.build();
}

/**
* 지출 내역 수정시 사용되는 user필드가 null이며, 사용자 정의 지출 카테고리를 사용하는 지출 내역으로 변환
*/
public Spending toEntity(SpendingCustomCategory spendingCustomCategory) {
return Spending.builder()
.amount(amount)
.category(icon)
.spendAt(spendAt.atStartOfDay())
.accountName(accountName)
.memo(memo)
.spendingCustomCategory(spendingCustomCategory)
.build();
}

@Schema(hidden = true)
public boolean isCustomCategory() {
return !categoryId.equals(-1L);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,11 @@ public class SpendingUpdateService {

@Transactional
public Spending updateSpending(Spending spending, SpendingReq request) {
if (!request.isCustomCategory()) {
spending.update(request.toEntity());
} else {
SpendingCustomCategory customCategory = spendingCustomCategoryService.readSpendingCustomCategory(request.categoryId())
.orElseThrow(() -> new SpendingErrorException(SpendingErrorCode.NOT_FOUND_CUSTOM_CATEGORY));
spending.update(request.toEntity(customCategory));
}
SpendingCustomCategory customCategory = (request.isCustomCategory())
? spendingCustomCategoryService.readSpendingCustomCategory(request.categoryId()).orElseThrow(() -> new SpendingErrorException(SpendingErrorCode.NOT_FOUND_CUSTOM_CATEGORY))
: null;

spending.update(request.amount(), request.icon(), request.spendAt().atStartOfDay(), request.accountName(), request.memo(), customCategory);

return spending;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public static UserProfileDto from(User user, OauthAccountDto oauthAccount) {
.profileImageUrl(Objects.toString(user.getProfileImageUrl(), ""))
.phone(user.getPhone())
.profileVisibility(user.getProfileVisibility())
.locked(user.getLocked())
.locked(user.isLocked())
.notifySetting(user.getNotifySetting())
.isGeneralSignUp(user.isGeneralSignedUpUser())
.createdAt(user.getCreatedAt())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public static UserDetails from(User user) {
.userId(user.getId())
.username(user.getUsername())
.authorities(List.of(new CustomGrantedAuthority(user.getRole().getType())))
.accountNonLocked(user.getLocked())
.accountNonLocked(user.isLocked())
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import kr.co.pennyway.api.common.exception.PhoneVerificationErrorCode;
import kr.co.pennyway.api.config.ExternalApiDBTestConfig;
import kr.co.pennyway.api.config.ExternalApiIntegrationTest;
import kr.co.pennyway.api.config.fixture.UserFixture;
import kr.co.pennyway.domain.common.redis.phone.PhoneCodeKeyType;
import kr.co.pennyway.domain.common.redis.phone.PhoneCodeService;
import kr.co.pennyway.domain.domains.oauth.domain.Oauth;
Expand All @@ -14,8 +15,6 @@
import kr.co.pennyway.domain.domains.user.domain.User;
import kr.co.pennyway.domain.domains.user.exception.UserErrorCode;
import kr.co.pennyway.domain.domains.user.service.UserService;
import kr.co.pennyway.domain.domains.user.type.ProfileVisibility;
import kr.co.pennyway.domain.domains.user.type.Role;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
Expand All @@ -42,10 +41,8 @@
@AutoConfigureMockMvc
@TestClassOrder(ClassOrderer.OrderAnnotation.class)
public class AuthControllerIntegrationTest extends ExternalApiDBTestConfig {
private final String expectedUsername = "jayang";
private final String expectedPhone = "010-1234-5678";
private final String expectedCode = "123456";
private final String expectedOauthId = "oauthId";

@Autowired
private MockMvc mockMvc;
Expand All @@ -66,40 +63,6 @@ void setUp(WebApplicationContext webApplicationContext) {
.build();
}

/**
* 일반 회원가입 유저 생성
*/
private User createGeneralSignedUser() {
return User.builder()
.name("페니웨이")
.username(expectedUsername)
.password("dkssudgktpdy1")
.phone("010-1234-5678")
.role(Role.USER)
.profileVisibility(ProfileVisibility.PUBLIC)
.build();
}

/**
* OAuth로 가입한 유저 생성 (password가 NULL)
*/
private User createOauthSignedUser() {
return User.builder()
.name("페니웨이")
.username(expectedUsername)
.phone("010-1234-5678")
.role(Role.USER)
.profileVisibility(ProfileVisibility.PUBLIC)
.build();
}

/**
* User에 연결된 Oauth 생성
*/
private Oauth createOauthAccount(User user) {
return Oauth.of(Provider.KAKAO, expectedOauthId, user);
}

@Nested
@Order(1)
@DisplayName("[2] 전화번호 검증 테스트")
Expand All @@ -110,7 +73,7 @@ class GeneralSignUpPhoneVerifyTest {
void generalSignUpFailBecauseAlreadyGeneralSignUp() throws Exception {
// given
phoneCodeService.create(expectedPhone, expectedCode, PhoneCodeKeyType.SIGN_UP);
given(userService.readUserByPhone(expectedPhone)).willReturn(Optional.of(createGeneralSignedUser()));
given(userService.readUserByPhone(expectedPhone)).willReturn(Optional.of(UserFixture.GENERAL_USER.toUser()));

// when
ResultActions resultActions = performPhoneVerificationRequest(expectedCode);
Expand Down Expand Up @@ -187,7 +150,7 @@ void generalSignUpSuccess() throws Exception {
void generalSignUpSuccessWithOauth() throws Exception {
// given
phoneCodeService.create(expectedPhone, expectedCode, PhoneCodeKeyType.SIGN_UP);
given(userService.readUserByPhone(expectedPhone)).willReturn(Optional.of(createOauthSignedUser()));
given(userService.readUserByPhone(expectedPhone)).willReturn(Optional.of(UserFixture.OAUTH_USER.toUser()));

// when
ResultActions resultActions = performPhoneVerificationRequest(expectedCode);
Expand All @@ -197,7 +160,7 @@ void generalSignUpSuccessWithOauth() throws Exception {
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.sms.code").value(true))
.andExpect(jsonPath("$.data.sms.oauth").value(true))
.andExpect(jsonPath("$.data.sms.username").value(expectedUsername))
.andExpect(jsonPath("$.data.sms.username").value(UserFixture.OAUTH_USER.getUsername()))
.andDo(print());
}

Expand Down Expand Up @@ -261,7 +224,7 @@ void generalSignUpSuccess() throws Exception {
}

private ResultActions performGeneralSignUpRequest(String code) throws Exception {
SignUpReq.General request = new SignUpReq.General(expectedUsername, "pennyway", "dkssudgktpdy1", expectedPhone, code);
SignUpReq.General request = new SignUpReq.General(UserFixture.GENERAL_USER.getUsername(), "pennyway", "dkssudgktpdy1", expectedPhone, code);
return mockMvc.perform(
post("/v1/auth/sign-up")
.contentType(MediaType.APPLICATION_JSON)
Expand All @@ -288,7 +251,7 @@ void syncWithOauthSignUpFailBecauseInvalidCode() throws Exception {
String invalidCode = "111111";

// when
ResultActions resultActions = performSyncWithOauthSignUpRequest(invalidCode);
ResultActions resultActions = performSyncWithOauthSignUpRequest(expectedPhone, invalidCode);

// then
resultActions
Expand All @@ -304,13 +267,12 @@ void syncWithOauthSignUpFailBecauseInvalidCode() throws Exception {
@DisplayName("인증번호가 일치하는 경우 200 OK를 반환하고, 기존의 소셜 계정과 연동된 회원가입이 완료된다.")
void syncWithOauthSignUpSuccess() throws Exception {
// given
phoneCodeService.create(expectedPhone, expectedCode, PhoneCodeKeyType.SIGN_UP);
User user = createOauthSignedUser();
userService.createUser(user);
oauthService.createOauth(createOauthAccount(user));
User user = userService.createUser(UserFixture.OAUTH_USER.toUser());
oauthService.createOauth(Oauth.of(Provider.KAKAO, "oauthId", user));
phoneCodeService.create(user.getPhone(), expectedCode, PhoneCodeKeyType.SIGN_UP);

// when
ResultActions resultActions = performSyncWithOauthSignUpRequest(expectedCode);
ResultActions resultActions = performSyncWithOauthSignUpRequest(user.getPhone(), expectedCode);

// then
resultActions
Expand All @@ -323,7 +285,7 @@ void syncWithOauthSignUpSuccess() throws Exception {
assertNotNull(user.getPassword());
}

private ResultActions performSyncWithOauthSignUpRequest(String code) throws Exception {
private ResultActions performSyncWithOauthSignUpRequest(String expectedPhone, String code) throws Exception {
SignUpReq.SyncWithOauth request = new SignUpReq.SyncWithOauth("dkssudgktpdy1", expectedPhone, code);
return mockMvc.perform(
post("/v1/auth/link-oauth")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import kr.co.pennyway.domain.domains.oauth.exception.OauthErrorCode;
import kr.co.pennyway.domain.domains.oauth.service.OauthService;
import kr.co.pennyway.domain.domains.oauth.type.Provider;
import kr.co.pennyway.domain.domains.user.domain.NotifySetting;
import kr.co.pennyway.domain.domains.user.domain.User;
import kr.co.pennyway.domain.domains.user.service.UserService;
import kr.co.pennyway.domain.domains.user.type.ProfileVisibility;
Expand Down Expand Up @@ -87,6 +88,7 @@ private User createGeneralSignedUser() {
.phone("010-1234-5678")
.role(Role.USER)
.profileVisibility(ProfileVisibility.PUBLIC)
.notifySetting(NotifySetting.of(true, true, true))
.build();
}

Expand All @@ -100,6 +102,7 @@ private User createOauthSignedUser() {
.phone("010-1234-5678")
.role(Role.USER)
.profileVisibility(ProfileVisibility.PUBLIC)
.notifySetting(NotifySetting.of(true, true, true))
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import kr.co.pennyway.domain.domains.oauth.type.Provider;
import kr.co.pennyway.domain.domains.user.domain.User;
import kr.co.pennyway.domain.domains.user.service.UserService;
import kr.co.pennyway.domain.domains.user.type.ProfileVisibility;
import kr.co.pennyway.domain.domains.user.type.Role;
import kr.co.pennyway.infra.common.exception.JwtErrorCode;
import kr.co.pennyway.infra.common.oidc.OidcDecodePayload;
Expand Down Expand Up @@ -88,13 +87,7 @@ class SignOut {

@BeforeEach
void setUp() {
User user = User.builder()
.username("pennyway")
.password("password")
.profileVisibility(ProfileVisibility.PUBLIC)
.role(Role.USER)
.locked(Boolean.FALSE)
.build();
User user = UserFixture.GENERAL_USER.toUser();
userService.createUser(user);
userId = user.getId();
expectedAccessToken = accessTokenProvider.generateToken(AccessTokenClaim.of(user.getId(), Role.USER.getType()));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package kr.co.pennyway.api.apis.auth.service;

import kr.co.pennyway.api.apis.auth.dto.UserSyncDto;
import kr.co.pennyway.api.config.fixture.UserFixture;
import kr.co.pennyway.domain.domains.user.domain.User;
import kr.co.pennyway.domain.domains.user.exception.UserErrorCode;
import kr.co.pennyway.domain.domains.user.exception.UserErrorException;
Expand All @@ -16,6 +17,7 @@
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;

@ExtendWith(MockitoExtension.class)
Expand Down Expand Up @@ -51,43 +53,42 @@ void isSignedUserWhenGeneralReturnFalse() {
@Test
void isSignedUserWhenGeneralReturnTrue() {
// given
given(userService.readUserByPhone(phone)).willReturn(Optional.of(User.builder().username("pennyway").password(null).build()));
given(userService.readUserByPhone(phone)).willReturn(Optional.of(UserFixture.OAUTH_USER.toUser()));

// when
UserSyncDto userSync = userGeneralSignService.isSignUpAllowed(phone);

// then
assertTrue(userSync.isSignUpAllowed());
assertTrue(userSync.isExistAccount());
assertEquals("pennyway", userSync.username());
assertEquals(UserFixture.OAUTH_USER.getUsername(), userSync.username());
}

@DisplayName("일반 회원가입 시, 이미 일반회원 가입된 회원인 경우 계정 생성 불가 응답을 반환한다.")
@Test
void isSignedUserWhenGeneralThrowUserErrorException() {
// given
given(userService.readUserByPhone(phone)).willReturn(
Optional.of(User.builder().username("pennyway").password("password").build()));
given(userService.readUserByPhone(phone)).willReturn(Optional.of(UserFixture.GENERAL_USER.toUser()));

// when
UserSyncDto userSync = userGeneralSignService.isSignUpAllowed(phone);

// then
assertFalse(userSync.isSignUpAllowed());
assertTrue(userSync.isExistAccount());
assertEquals("pennyway", userSync.username());
assertEquals(UserFixture.GENERAL_USER.getUsername(), userSync.username());
}

@DisplayName("로그인 시, 유저가 존재하고 비밀번호가 일치하면 User를 반환한다.")
@Test
void readUserIfValidReturnUser() {
// given
User user = User.builder().username("pennyway").password("password").build();
given(userService.readUserByUsername("pennyway")).willReturn(Optional.of(user));
given(passwordEncoder.matches("password", user.getPassword())).willReturn(true);
User user = UserFixture.GENERAL_USER.toUser();
given(userService.readUserByUsername(user.getUsername())).willReturn(Optional.of(user));
given(passwordEncoder.matches(user.getPassword(), user.getPassword())).willReturn(true);

// when
User result = userGeneralSignService.readUserIfValid("pennyway", "password");
User result = userGeneralSignService.readUserIfValid(user.getUsername(), user.getPassword());

// then
assertEquals(result, user);
Expand All @@ -97,8 +98,7 @@ void readUserIfValidReturnUser() {
@Test
void readUserIfNotFound() {
// given
given(userService.readUserByUsername("pennyway")).willThrow(
new UserErrorException(UserErrorCode.NOT_FOUND));
given(userService.readUserByUsername("pennyway")).willThrow(new UserErrorException(UserErrorCode.NOT_FOUND));

// when - then
UserErrorException exception = assertThrows(UserErrorException.class, () -> userGeneralSignService.readUserIfValid("pennyway", "password"));
Expand All @@ -109,8 +109,8 @@ void readUserIfNotFound() {
@Test
void readUserIfNotMatchedPassword() {
// given
User user = User.builder().username("pennyway").password("password").build();
given(userService.readUserByUsername("pennyway")).willReturn(Optional.of(user));
User user = UserFixture.GENERAL_USER.toUser();
given(userService.readUserByUsername(any())).willReturn(Optional.of(user));
given(passwordEncoder.matches("password", user.getPassword())).willReturn(false);

// when - then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,18 +219,15 @@ class UpdateSpending {
void updateSpendingSuccess() throws Exception {
// given
User user = userService.createUser(UserFixture.GENERAL_USER.toUser());
Spending spending = SpendingFixture.GENERAL_SPENDING.toSpending(user);
Spending spending = spendingService.createSpending(SpendingFixture.GENERAL_SPENDING.toSpending(user));

SpendingReq request = new SpendingReq(20000, -1L, SpendingCategory.LIVING, LocalDate.now(), "수정된 소비처", "수정된 메모");
spendingService.createSpending(spending);

// when
ResultActions resultActions = performUpdateSpending(request, user, spending.getId());

// then
resultActions
.andDo(print())
.andExpect(status().isOk());
resultActions.andDo(print()).andExpect(status().isOk());

Spending updatedSpending = spendingService.readSpending(spending.getId()).get();
Assertions.assertEquals(request.memo(), updatedSpending.getMemo());
Expand Down
Loading

0 comments on commit 3453d88

Please sign in to comment.