Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

회원의 닉네임을 일정주기를 통해 변경할 수 있도록 구현 #498

Merged
merged 7 commits into from
Sep 9, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import com.votogether.domain.member.entity.vo.Gender;
import com.votogether.domain.member.entity.vo.Nickname;
import com.votogether.domain.member.entity.vo.SocialType;
import com.votogether.domain.member.exception.MemberExceptionType;
import com.votogether.global.exception.BadRequestException;
import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
Expand All @@ -15,6 +17,7 @@
import jakarta.persistence.Id;
import jakarta.persistence.Index;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.EqualsAndHashCode;
Expand Down Expand Up @@ -77,10 +80,24 @@ public static Member from(final KakaoMemberResponse response) {
.build();
}

public void changeNickname(final String nickname) {
public void changeNicknameByCycle(final String nickname, final Long days) {
if (nickname.startsWith(INITIAL_NICKNAME_PREFIX)) {
throw new BadRequestException(MemberExceptionType.NOT_ALLOWED_INITIAL_NICKNAME_PREFIX);
}
if (isNotPassedChangingCycle(days) && isNotInitialNickname()) {
throw new BadRequestException(MemberExceptionType.NOT_PASSED_NICKNAME_CHANGING_CYCLE);
}
this.nickname = new Nickname(nickname);
}

private boolean isNotPassedChangingCycle(final Long days) {
return this.getUpdatedAt().isAfter(LocalDateTime.now().minusDays(days));
}

private boolean isNotInitialNickname() {
return this.nickname.nonStartsWith(INITIAL_NICKNAME_PREFIX);
}

public void changeNicknameByReport() {
final String reportedNickname = "Pause1" + RandomStringUtils.random(9, true, true);
this.nickname = new Nickname(reportedNickname);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,8 @@ private void validateNickname(final String nickname) {
}
}

public boolean nonStartsWith(final String prefix) {
return !this.value.startsWith(prefix);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public enum MemberExceptionType implements ExceptionType {
INVALID_AGE(804, "존재할 수 없는 연령입니다."),
ALREADY_ASSIGNED_GENDER(805, "이미 성별이 할당되어 있습니다."),
ALREADY_ASSIGNED_BIRTH_YEAR(806, "이미 출생년도가 할당되어 있습니다."),
NOT_PASSED_NICKNAME_CHANGING_CYCLE(807, "최소 닉네임 변경주기가 지나지 않았습니다."),
NOT_ALLOWED_INITIAL_NICKNAME_PREFIX(808, "초기 닉네임에 포함된 접두어로 닉네임을 변경할 수 없습니다."),
;

private final int code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
@Service
public class MemberService {

private static final Long NICKNAME_CHANGING_CYCLE = 14L;

private final MemberRepository memberRepository;
private final MemberCategoryRepository memberCategoryRepository;
private final PostRepository postRepository;
Expand Down Expand Up @@ -68,7 +70,7 @@ public MemberInfoResponse findMemberInfo(final Member member) {
@Transactional
public void changeNickname(final Member member, final String nickname) {
validateExistentNickname(nickname);
member.changeNickname(nickname);
member.changeNicknameByCycle(nickname, NICKNAME_CHANGING_CYCLE);
}

private void validateExistentNickname(final String nickname) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package com.votogether.domain.member.entity;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import com.votogether.domain.member.entity.vo.Gender;
import com.votogether.domain.member.entity.vo.SocialType;
import com.votogether.global.exception.BadRequestException;
import java.time.LocalDateTime;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;

class MemberTest {

@Nested
@DisplayName("닉네임을 주기에 따라 변경하는 경우")
class ChangeNicknameByCycle {

@Test
@DisplayName("15일전에 변경된 닉네임은 14일 주기로 변경할 때 성공적으로 변경된다.")
void success() {
// given
Member member = Member.builder()
.nickname("저문")
.gender(Gender.MALE)
.birthYear(1966)
.socialId("abc123")
.socialType(SocialType.KAKAO)
.build();

LocalDateTime now = LocalDateTime.now().minusDays(15L);
ReflectionTestUtils.setField(member, "createdAt", now);
ReflectionTestUtils.setField(member, "updatedAt", now.plusHours(1L));

// when
member.changeNicknameByCycle("저라니", 14L);

// then
assertThat(member.getNickname()).isEqualTo("저라니");
}

@Test
@DisplayName("13일 전에 변경된 닉네임은 14일 주기로 변경하더라도 한번도 닉네임을 변경하지 않았다면 성공적으로 변경된다.")
void successFirstChange() {
// given
Member member = Member.builder()
.nickname("익명의손님fFp4vAgX2d")
.gender(Gender.MALE)
.birthYear(1966)
.socialId("abc123")
.socialType(SocialType.KAKAO)
.build();

LocalDateTime now = LocalDateTime.now().minusDays(13L);
ReflectionTestUtils.setField(member, "createdAt", now);
ReflectionTestUtils.setField(member, "updatedAt", now.plusHours(1L));

// when
member.changeNicknameByCycle("저라니", 14L);

// then
assertThat(member.getNickname()).isEqualTo("저라니");
}

@Test
@DisplayName("13일 전에 변경된 닉네임은 14일 주기로 변경할 때 변경에 실패한다.")
void fail() {
// given
Member member = Member.builder()
.nickname("저문")
.gender(Gender.MALE)
.birthYear(1966)
.socialId("abc123")
.socialType(SocialType.KAKAO)
.build();

LocalDateTime createdTime = LocalDateTime.now().minusDays(20L);
LocalDateTime updatedTime = LocalDateTime.now().minusDays(13L);
ReflectionTestUtils.setField(member, "createdAt", createdTime);
ReflectionTestUtils.setField(member, "updatedAt", updatedTime);

// when, then
assertThatThrownBy(() -> member.changeNicknameByCycle("저라니", 14L))
.isInstanceOf(BadRequestException.class)
.hasMessage("최소 닉네임 변경주기가 지나지 않았습니다.");
}

@Test
@DisplayName("초기 닉네임의 접두사가 포함되어 있으면 예외가 발생한다.")
void notAllowedChangeToInitialNicknamePrefix() {
// given
Member member = Member.builder()
.nickname("저문")
.gender(Gender.MALE)
.birthYear(1966)
.socialId("abc123")
.socialType(SocialType.KAKAO)
.build();

LocalDateTime createdTime = LocalDateTime.now().minusDays(20L);
LocalDateTime updatedTime = LocalDateTime.now().minusDays(7L);
ReflectionTestUtils.setField(member, "createdAt", createdTime);
ReflectionTestUtils.setField(member, "updatedAt", updatedTime);

// when, then
assertThatThrownBy(() -> member.changeNicknameByCycle("익명의손님저라니", 14L))
.isInstanceOf(BadRequestException.class)
.hasMessage("초기 닉네임에 포함된 접두어로 닉네임을 변경할 수 없습니다.");
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,24 @@ void register() {
class ChangeNickname {

@Test
@DisplayName("주어질 때 정상적으로 닉네임을 변경한다.")
@DisplayName("한번도 변경되지 않았다면 닉네임 변경 주기에 상관없이 닉네임을 변경한다.")
void changeNickname() {
// given
Member member = Member.builder()
.nickname("익명의손님fFp4vAgX2d")
.gender(Gender.MALE)
.birthYear(1966)
.socialId("abc123")
.socialType(SocialType.KAKAO)
.build();
String newNickname = "jeomxon";
Member member = memberRepository.save(MemberFixtures.FEMALE_30.get());
Member savedMember = memberRepository.save(member);

// when
memberService.changeNickname(member, newNickname);
memberService.changeNickname(savedMember, newNickname);

// then
assertThat(member.getNickname()).isEqualTo(newNickname);
assertThat(savedMember.getNickname()).isEqualTo(newNickname);
}

@ParameterizedTest
Expand Down Expand Up @@ -136,6 +143,27 @@ void changeNicknameEqualToPrevious() {
.hasMessage("이미 중복된 닉네임이 존재합니다.");
}

@Test
@DisplayName("최초 닉네임을 변경한 후 닉네임 변경 주기가 지나지 않았다면 예외가 발생한다.")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

닉네임 변경 이후 14일이 지나면 닉네임이 변경가능한지 여부도 테스트해볼 수 없을까요? 😎

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

한번 작성해보겠습니다..!

void changeNicknameThrowsExceptionNotPassedChangingCycle() {
// given
Member member = Member.builder()
.nickname("익명의손님fFp4vAgX2d")
.gender(Gender.MALE)
.birthYear(1966)
.socialId("abc123")
.socialType(SocialType.KAKAO)
.build();
Member savedMember = memberRepository.save(member);

memberService.changeNickname(savedMember, "저문");

// when, then
assertThatThrownBy(() -> memberService.changeNickname(savedMember, "저라니"))
.isInstanceOf(BadRequestException.class)
.hasMessage("최소 닉네임 변경주기가 지나지 않았습니다.");
}

}

@Nested
Expand Down