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

feat: 회원 정보 조회 기능 구현 #37

Merged
merged 11 commits into from
Dec 30, 2023
Merged
14 changes: 14 additions & 0 deletions src/docs/asciidoc/member/member-api.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,17 @@ include::{snippets}/member-controller-docs-test/check-email-duplicate/http-reque

include::{snippets}/member-controller-docs-test/check-email-duplicate/http-response.adoc[]
include::{snippets}/member-controller-docs-test/check-email-duplicate/response-fields.adoc[]

[[Get-Member]]
== 회원 정보 조회

회원 정보 조회 API 입니다.

=== HttpRequest

include::{snippets}/member-controller-docs-test/get-member/http-request.adoc[]

=== HttpResponse

include::{snippets}/member-controller-docs-test/get-member/http-response.adoc[]
include::{snippets}/member-controller-docs-test/get-member/response-fields.adoc[]
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import com.backoffice.upjuyanolja.domain.member.dto.request.SignUpRequest;
import com.backoffice.upjuyanolja.domain.member.dto.response.CheckEmailDuplicateResponse;
import com.backoffice.upjuyanolja.domain.member.dto.response.GetMemberResponse;
import com.backoffice.upjuyanolja.domain.member.dto.response.SignUpResponse;
import com.backoffice.upjuyanolja.domain.member.service.MemberGetService;
import com.backoffice.upjuyanolja.domain.member.service.MemberRegisterService;
import com.backoffice.upjuyanolja.global.common.ApiResponse;
import com.backoffice.upjuyanolja.global.common.ApiResponse.SuccessResponse;
Expand All @@ -11,6 +13,7 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
Expand All @@ -23,6 +26,7 @@
public class MemberController {

private final MemberRegisterService memberRegisterService;
private final MemberGetService memberGetService;

@PostMapping("/signup")
public ResponseEntity<SuccessResponse<SignUpResponse>> signup(
Expand All @@ -44,4 +48,14 @@ public ResponseEntity<SuccessResponse<CheckEmailDuplicateResponse>> checkEmailDu
.data(memberRegisterService.checkEmailDuplicate(email))
.build());
}

@GetMapping("/{memberId}")
public ResponseEntity<SuccessResponse<GetMemberResponse>> getMember(
// TODO 시큐리티 로그인 적용 이후 토큰에서 memberId 받아오도록 수정
@PathVariable(name = "memberId") long memberId) {
return ApiResponse.success(HttpStatus.OK, SuccessResponse.<GetMemberResponse>builder()
.message("성공적으로 회원 정보를 조회했습니다.")
.data(memberGetService.getMember(memberId))
.build());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.backoffice.upjuyanolja.domain.member.dto.response;

import com.backoffice.upjuyanolja.domain.member.entity.Member;
import lombok.Builder;

@Builder
public record GetMemberResponse(
JeongUijeong marked this conversation as resolved.
Show resolved Hide resolved
long memberId,
String email,
String name,
String phoneNumber
) {

JeongUijeong marked this conversation as resolved.
Show resolved Hide resolved
public static GetMemberResponse of(Member member) {
return GetMemberResponse.builder()
.memberId(member.getId())
.email(member.getEmail())
.name(member.getName())
.phoneNumber(member.getPhone())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.backoffice.upjuyanolja.domain.member.service;

import com.backoffice.upjuyanolja.domain.member.dto.response.GetMemberResponse;
import com.backoffice.upjuyanolja.domain.member.entity.Member;
import com.backoffice.upjuyanolja.domain.member.exception.MemberNotFoundException;
import com.backoffice.upjuyanolja.domain.member.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class MemberGetService {

private final MemberRepository memberRepository;

public GetMemberResponse getMember(long memberId) {
return GetMemberResponse.of(getMemberById(memberId));
}

public Member getMemberById(long memberId) {
return memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
import static org.springframework.restdocs.request.RequestDocumentation.queryParameters;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;

import com.backoffice.upjuyanolja.domain.member.dto.response.CheckEmailDuplicateResponse;
import com.backoffice.upjuyanolja.domain.member.dto.response.GetMemberResponse;
import com.backoffice.upjuyanolja.domain.member.service.MemberGetService;
import com.backoffice.upjuyanolja.domain.member.service.MemberRegisterService;
import com.backoffice.upjuyanolja.global.util.RestDocsSupport;
import org.junit.jupiter.api.DisplayName;
Expand All @@ -22,6 +25,9 @@ public class MemberControllerDocsTest extends RestDocsSupport {
@MockBean
private MemberRegisterService memberRegisterService;

@MockBean
private MemberGetService memberGetService;

@Test
@DisplayName("checkEmailDuplicate()는 이메일 중복 검사를 할 수 있다.")
void checkEmailDuplicate() throws Exception {
Expand All @@ -41,8 +47,41 @@ void checkEmailDuplicate() throws Exception {
parameterWithName("email").description("이메일")
),
responseFields(successResponseCommon()).and(
fieldWithPath("data.isExists").type(JsonFieldType.BOOLEAN).description("이메일 중복 여부")
fieldWithPath("data.isExists").type(JsonFieldType.BOOLEAN)
.description("이메일 중복 여부")
)
));
}
}

@Test
@DisplayName("getMember()는 회원 정보를 조회할 수 있다.")
void getMember() throws Exception {
// given
GetMemberResponse getMemberResponse = GetMemberResponse.builder()
.memberId(1L)
.email("[email protected]")
.name("test")
.phoneNumber("010-1234-1234")
.build();

given(memberGetService.getMember(any(Long.TYPE)))
.willReturn(getMemberResponse);

// when then
mockMvc.perform(get("/api/members/{memberId}", 1L))
.andDo(restDoc.document(
responseFields(successResponseCommon()).and(
fieldWithPath("data.memberId").type(JsonFieldType.NUMBER)
.description("회원 식별자"),
fieldWithPath("data.email").type(JsonFieldType.STRING)
.description("이메일"),
fieldWithPath("data.name").type(JsonFieldType.STRING)
.description("이름"),
fieldWithPath("data.phoneNumber").type(JsonFieldType.STRING)
.description("전화번호")
)
));

verify(memberGetService, times(1)).getMember(any(Long.TYPE));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

import com.backoffice.upjuyanolja.domain.member.controller.MemberController;
import com.backoffice.upjuyanolja.domain.member.dto.response.CheckEmailDuplicateResponse;
import com.backoffice.upjuyanolja.domain.member.dto.response.GetMemberResponse;
import com.backoffice.upjuyanolja.domain.member.exception.MemberNotFoundException;
import com.backoffice.upjuyanolja.domain.member.service.MemberGetService;
import com.backoffice.upjuyanolja.domain.member.service.MemberRegisterService;
import com.backoffice.upjuyanolja.global.security.AuthenticationConfig;
import com.fasterxml.jackson.databind.ObjectMapper;
Expand Down Expand Up @@ -42,6 +45,9 @@ public class MemberControllerTest {
@MockBean
private MemberRegisterService memberRegisterService;

@MockBean
private MemberGetService memberGetService;

@Nested
@DisplayName("checkEmailDuplicate()는")
class Context_createComment {
Expand Down Expand Up @@ -92,4 +98,37 @@ void notDuplicatedEmail_willSuccess() throws Exception {
verify(memberRegisterService, times(1)).checkEmailDuplicate(any(String.class));
}
}
}

@Nested
@DisplayName("getMember()는")
class Context_getMember {

@Test
@DisplayName("회원 정보를 조회할 수 있다.")
void _willSuccess() throws Exception {
// given
GetMemberResponse getMemberResponse = GetMemberResponse.builder()
.memberId(1L)
.email("[email protected]")
.name("test")
.phoneNumber("010-1234-1234")
.build();

given(memberGetService.getMember(any(Long.TYPE)))
.willReturn(getMemberResponse);

// when then
mockMvc.perform(get("/api/members/{memberId}", 1L))
.andExpect(status().isOk())
.andExpect(jsonPath("$.message").isString())
.andExpect(jsonPath("$.data").isMap())
.andExpect(jsonPath("$.data.memberId").isNumber())
.andExpect(jsonPath("$.data.email").isString())
.andExpect(jsonPath("$.data.name").isString())
.andExpect(jsonPath("$.data.phoneNumber").isString())
.andDo(print());

verify(memberGetService, times(1)).getMember(any(Long.class));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.backoffice.upjuyanolja.domain.member.unit.service;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import com.backoffice.upjuyanolja.domain.member.dto.response.GetMemberResponse;
import com.backoffice.upjuyanolja.domain.member.entity.Authority;
import com.backoffice.upjuyanolja.domain.member.entity.Member;
import com.backoffice.upjuyanolja.domain.member.exception.MemberNotFoundException;
import com.backoffice.upjuyanolja.domain.member.repository.MemberRepository;
import com.backoffice.upjuyanolja.domain.member.service.MemberGetService;
import java.util.Optional;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.transaction.annotation.Transactional;

@Transactional
@ExtendWith(MockitoExtension.class)
public class MemberGetServiceTest {

@InjectMocks
private MemberGetService memberGetService;

@Mock
private MemberRepository memberRepository;

@Nested
@DisplayName("getMember()는")
class Context_getMember {

@Test
@DisplayName("회원 정보를 조회할 수 있다.")
void _willSuccess() {
// given
Member member = Member.builder()
.id(1L)
.email("[email protected]")
.password("$10$ygrAExVYmFTkZn2d0.Pk3Ot5CNZwIBjZH5f.WW0AnUq4w4PtBi9Nm")
.name("test")
.phone("010-1234-1234")
.imageUrl(
"https://fastly.picsum.photos/id/866/200/300.jpg?hmac=rcadCENKh4rD6MAp6V_ma-AyWv641M4iiOpe1RyFHeI")
.authority(Authority.ROLE_USER)
.build();
given(memberRepository.findById(any(Long.TYPE))).willReturn(Optional.of(member));

// when
GetMemberResponse result = memberGetService.getMember(1L);

// then
assertThat(result.memberId()).isEqualTo(1L);
assertThat(result.email()).isEqualTo("[email protected]");
assertThat(result.name()).isEqualTo("test");
assertThat(result.phoneNumber()).isEqualTo("010-1234-1234");

verify(memberRepository, times(1)).findById(any(Long.TYPE));
}

@Test
@DisplayName("회원을 찾을 수 없으면, 익셉션을 던진다.")
void memberNotFound_willFail() {
// given
given(memberRepository.findById(any(Long.TYPE))).willReturn(Optional.empty());

// when
Throwable exception = assertThrows(MemberNotFoundException.class, () -> {
memberGetService.getMember(1L);
});

// then
assertEquals(exception.getMessage(), "회원 정보를 찾을 수 없습니다.");

verify(memberRepository, times(1)).findById(any(Long.TYPE));
}
}
}