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 @@ -80,16 +80,18 @@ public static Member from(final KakaoMemberResponse response) {
.build();
}

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

private boolean isNotPassedChangingCycle() {
private boolean isNotPassedChangingCycle(final Long days) {
System.out.println("this.getCreatedAt() = " + this.getCreatedAt());
System.out.println("this.getUpdatedAt() = " + this.getUpdatedAt());
return (!this.getCreatedAt().equals(this.getUpdatedAt())) &&
Copy link
Collaborator

Choose a reason for hiding this comment

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

현재는 변경 가능한 필드가 닉네임밖에 없어서 괜찮을 것 같은데, 변경 가능한 필드가 생긴다면 조금 더 고민이 필요한 부분인 것 같네요 ㅎㅎ

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

맞습니다 이 부분에 대해서 많이 생각을 했었는데, 이 방식으로 구현한만큼 잘 인지하고 있어야한다고 생각했어요.
현재는 문제가 없을 것 같아서 이대로 가져갈 생각입니다!

(this.getUpdatedAt().isAfter(LocalDateTime.now().minusDays(14L)));
(this.getUpdatedAt().isAfter(LocalDateTime.now().minusDays(days)));
}

public void changeNicknameByReport() {
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,108 @@
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.common.BaseEntity;
import com.votogether.domain.member.entity.vo.Gender;
import com.votogether.domain.member.entity.vo.SocialType;
import com.votogether.global.exception.BadRequestException;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

class MemberTest {

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

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

Field createdAtField = BaseEntity.class.getDeclaredField("createdAt");
Field updatedAtField = BaseEntity.class.getDeclaredField("updatedAt");
createdAtField.setAccessible(true);
updatedAtField.setAccessible(true);

LocalDateTime now = LocalDateTime.now().minusDays(15L);
createdAtField.set(member, now);
updatedAtField.set(member, now);

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

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

Choose a reason for hiding this comment

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

@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);

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

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

리플렉션을 사용해서 테스트를 잘 해주셨네요 👍👍

테스트를 위한 리플렉션 유틸 클래스도 있어서 이를 활용하면 더 좋을 것 같아요! throws Exception 부분도 제거할 수 있을 것 같아요 ㅎㅎ

한 가지 궁금한 점은 리플렉션을 사용하면 createdAt, updatedAt 값을 설정할 수 있기에 메서드에 날짜를 받도록 수정하지 않아도 테스트할 수 있었을 것 같은데 메서드를 수정하신 이유가 궁금합니다!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

리플렉션 유틸 클래스가 있었군요..! 적용해보도록 할게요 감사합니다.
Member가 정책에 대한 날짜를 가지고 있는 것보다 application계층에서 넘겨주는 것이 비즈니스 로직을 잘 나타낼 수 있다고 생각해서 변경했습니다!
정책에 따라 변경될 수 있는 부분이라는 생각이 드는데, 만약 정책이 변경되어서 코드를 변경하러 갈 때 저라면 비즈니스 로직이 있는 부분에서 수정이 가능하도록 하는 것이 자연스럽다고 생각했어요.

하지만 현재 로직이 문제가 있는 것 같아서 내부 로직을 다시 수정해볼게요..!


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

Field createdAtField = BaseEntity.class.getDeclaredField("createdAt");
Field updatedAtField = BaseEntity.class.getDeclaredField("updatedAt");
createdAtField.setAccessible(true);
updatedAtField.setAccessible(true);

LocalDateTime now = LocalDateTime.now().minusDays(13L);
createdAtField.set(member, now);
updatedAtField.set(member, now);

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

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

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

Field createdAtField = BaseEntity.class.getDeclaredField("createdAt");
Field updatedAtField = BaseEntity.class.getDeclaredField("updatedAt");
createdAtField.setAccessible(true);
updatedAtField.setAccessible(true);

LocalDateTime createdTime = LocalDateTime.now().minusDays(20L);
LocalDateTime updatedTime = LocalDateTime.now().minusDays(13L);
createdAtField.set(member, createdTime);
updatedAtField.set(member, updatedTime);

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

}

}