Skip to content

Commit

Permalink
회원 탈퇴 기능 구현 (#162)
Browse files Browse the repository at this point in the history
* feat: (#141) 회원 탈퇴 기능 구현

* chore: (#141) 회원 탈퇴 swagger적용
  • Loading branch information
jeomxon authored and tjdtls690 committed Sep 12, 2023
1 parent 1a7145b commit e116ad1
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand Down Expand Up @@ -50,4 +51,15 @@ public ResponseEntity<Void> changeNickname(
return ResponseEntity.ok().build();
}

@Operation(summary = "회원 탈퇴", description = "서비스를 탈퇴한다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "회원 탈퇴 성공"),
@ApiResponse(responseCode = "404", description = "존재하지 않는 회원")
})
@DeleteMapping("/me/delete")
public ResponseEntity<Void> deleteMember(@Auth final Member member) {
memberService.deleteMember(member);
return ResponseEntity.noContent().build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ private Member(
public static Member from(final KakaoMemberResponse response) {
final NicknameNumberGenerator nicknameNumberGenerator = new NicknameNumberGenerator();
return Member.builder()
.nickname("익명의 손님" + nicknameNumberGenerator.generate())
.nickname("익명의손님" + nicknameNumberGenerator.generate())
.gender(Gender.valueOf(response.kakaoAccount().gender().toUpperCase()))
.ageRange(response.kakaoAccount().ageRange())
.birthday(response.kakaoAccount().birthday())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,11 @@ private void validateExistentNickname(final String nickname) {
}
}

@Transactional
public void deleteMember(final Member member) {
final Member existentMember = memberRepository.findById(member.getId())
.orElseThrow(() -> new NotFoundException(MemberExceptionType.NONEXISTENT_MEMBER));
memberRepository.delete(existentMember);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,58 +3,77 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.willDoNothing;

import com.votogether.domain.member.dto.MemberInfoResponse;
import com.votogether.domain.member.dto.MemberNicknameUpdateRequest;
import com.votogether.domain.member.entity.Gender;
import com.votogether.domain.member.entity.Member;
import com.votogether.domain.member.entity.SocialType;
import com.votogether.domain.member.service.MemberService;
import com.votogether.fixtures.MemberFixtures;
import com.votogether.global.jwt.TokenPayload;
import com.votogether.global.jwt.TokenProcessor;
import io.restassured.http.ContentType;
import io.restassured.module.mockmvc.RestAssuredMockMvc;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.web.context.WebApplicationContext;

@Import(TokenProcessor.class)
@WebMvcTest(MemberController.class)
class MemberControllerTest {

@MockBean
MemberService memberService;

@Autowired
@MockBean
TokenProcessor tokenProcessor;

@BeforeEach
void setUp() {
void setUp(final WebApplicationContext webApplicationContext) {
RestAssuredMockMvc.standaloneSetup(new MemberController(memberService));
RestAssuredMockMvc.webAppContextSetup(webApplicationContext);
}

@Test
@DisplayName("회원 정보를 조회한다.")
void findMemberInfo() {
void findMemberInfo() throws Exception {
// given
Member member = Member.builder()
.nickname("저문")
.gender(Gender.MALE)
.ageRange("20~29")
.socialId("abc123")
.socialType(SocialType.KAKAO)
.birthday("0101")
.point(1234)
.build();
TokenPayload tokenPayload = new TokenPayload(1L, 1L, 1L);
MemberInfoResponse memberInfoResponse = new MemberInfoResponse(
"저문",
1234,
0,
0
);

given(tokenProcessor.resolveToken(anyString())).willReturn("token");
given(tokenProcessor.parseToken(anyString())).willReturn(tokenPayload);
given(memberService.findById(anyLong())).willReturn(member);
given(memberService.findMemberInfo(any(Member.class))).willReturn(memberInfoResponse);

// when
MemberInfoResponse response = RestAssuredMockMvc
.given().log().all()
.headers(HttpHeaders.AUTHORIZATION, "Bearer token")
.when().get("/members/me")
.then().log().all()
.extract()
Expand All @@ -75,44 +94,72 @@ class ChangeNickname {

@Test
@DisplayName("변경에 성공하면 200을 반환한다.")
void changeNicknameSuccess() {
void changeNicknameSuccess() throws Exception {
// given
String nicknameToChange = "jeomxon";
MemberNicknameUpdateRequest memberNicknameUpdateRequest = new MemberNicknameUpdateRequest(nicknameToChange);
TokenPayload tokenPayload = new TokenPayload(1L, 1L, 1L);

given(tokenProcessor.resolveToken(anyString())).willReturn("token");
given(tokenProcessor.parseToken(anyString())).willReturn(tokenPayload);
given(memberService.findById(anyLong())).willReturn(MemberFixtures.FEMALE_20.get());
willDoNothing().given(memberService).changeNickname(any(Member.class), anyString());

// when, then
RestAssuredMockMvc
.given().log().all()
.headers(HttpHeaders.AUTHORIZATION, "Bearer token")
.contentType(ContentType.JSON)
.body(memberNicknameUpdateRequest)
.when().patch("/members/me/nickname")
.then().log().all()
.statusCode(HttpStatus.OK.value())
.extract();
.statusCode(HttpStatus.OK.value());
}

@Test
@DisplayName("변경에 실패하면 400을 반환한다.")
void changeNicknameFail() {
void changeNicknameFail() throws Exception {
// given
String nicknameToChange = "";
MemberNicknameUpdateRequest memberNicknameUpdateRequest = new MemberNicknameUpdateRequest(nicknameToChange);
TokenPayload tokenPayload = new TokenPayload(1L, 1L, 1L);

given(tokenProcessor.resolveToken(anyString())).willReturn("token");
given(tokenProcessor.parseToken(anyString())).willReturn(tokenPayload);
given(memberService.findById(anyLong())).willReturn(MemberFixtures.FEMALE_20.get());
willDoNothing().given(memberService).changeNickname(any(Member.class), anyString());

// when, then
RestAssuredMockMvc
.given().log().all()
.headers(HttpHeaders.AUTHORIZATION, "Bearer token")
.contentType(ContentType.JSON)
.body(memberNicknameUpdateRequest)
.when().patch("/members/me/nickname")
.then().log().all()
.statusCode(HttpStatus.BAD_REQUEST.value())
.extract();
.statusCode(HttpStatus.BAD_REQUEST.value());
}

}

@Test
@DisplayName("회원 탈퇴에 성공하면 204를 반환한다.")
void deleteMember() throws Exception {
// given
TokenPayload tokenPayload = new TokenPayload(1L, 1L, 1L);

given(tokenProcessor.resolveToken(anyString())).willReturn("token");
given(tokenProcessor.parseToken(anyString())).willReturn(tokenPayload);
given(memberService.findById(anyLong())).willReturn(MemberFixtures.FEMALE_20.get());
willDoNothing().given(memberService).deleteMember(MemberFixtures.FEMALE_20.get());

// when, then
RestAssuredMockMvc
.given().log().all()
.headers(HttpHeaders.AUTHORIZATION, "Bearer token")
.when().delete("/members/me/delete")
.then().log().all()
.statusCode(HttpStatus.NO_CONTENT.value());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,17 @@ void changeNicknameEqualToPrevious() {

}

@Test
@DisplayName("회원 탈퇴를 성공한다.")
void deleteMember() {
// given
Member member = memberRepository.save(MemberFixtures.MALE_20.get());

// when
memberService.deleteMember(member);

// then
assertThat(memberRepository.findAll()).isEmpty();
}

}

0 comments on commit e116ad1

Please sign in to comment.