Skip to content

Commit

Permalink
✨ [STMT-199] 내 정보 조회 API 구현 (#90)
Browse files Browse the repository at this point in the history
* ✨ [STMT-199] 내 정보 조회 API 구현

* ✅ [STMT-199] 멤버 정보 조회 유즈 케이스 테스트 코드 작성

* ✨ [STMT-199] 테스트 메서드 실행 전후로 SQL 문을 실행시켜 DB 초기 세팅 및 초기화 진행

* ✅ [STMT-199] 내 정보 조회 API 테스트 추가
  • Loading branch information
zxcv9203 authored Mar 7, 2024
1 parent 6499fd2 commit 8f6e1d1
Show file tree
Hide file tree
Showing 18 changed files with 182 additions and 35 deletions.
12 changes: 12 additions & 0 deletions src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,18 @@ include::{snippets}/validate_nickname/fail/invalid/response-fields.adoc[]
include::{snippets}/validate_nickname/fail/duplicate/response-body.adoc[]
include::{snippets}/validate_nickname/fail/duplicate/response-fields.adoc[]

=== 내 정보 조회

==== GET /api/v1/members/me

===== 요청
include::{snippets}/get-my-profile/success/http-request.adoc[]
include::{snippets}/get-my-profile/success/request-headers.adoc[]

===== 응답 (200)
include::{snippets}/get-my-profile/success/response-body.adoc[]
include::{snippets}/get-my-profile/success/response-fields.adoc[]

=== 사용자 정보 수정

==== PATCH /api/v1/members/me
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import com.stumeet.server.common.annotation.WebAdapter;
import com.stumeet.server.common.auth.model.LoginMember;
import com.stumeet.server.common.model.ApiResponse;
import com.stumeet.server.member.adapter.in.web.response.MemberProfileResponse;
import com.stumeet.server.member.application.port.in.MemberProfileUseCase;
import com.stumeet.server.member.application.port.in.command.MemberUpdateCommand;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.RequestMapping;

Expand All @@ -31,4 +33,15 @@ public ResponseEntity<ApiResponse<Void>> updateMyProfile(
HttpStatus.OK
);
}

@GetMapping("/me")
public ResponseEntity<ApiResponse<MemberProfileResponse>> getMyProfile(
@AuthenticationPrincipal LoginMember member
) {
MemberProfileResponse response = memberProfileUseCase.getProfileById(member.getMember().getId());
return new ResponseEntity<>(
ApiResponse.success(HttpStatus.OK.value(), "내 프로필 조회에 성공했습니다.", response),
HttpStatus.OK
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.stumeet.server.member.adapter.in.web.response;

import lombok.Builder;

@Builder
public record MemberProfileResponse(
Long id,
String image,
String nickname,
String region,
String profession,
String rank,
double experience
) {
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.stumeet.server.member.application.port.in;

import com.stumeet.server.member.adapter.in.web.response.MemberProfileResponse;
import com.stumeet.server.member.application.port.in.command.MemberSignupCommand;
import com.stumeet.server.member.application.port.in.command.MemberUpdateCommand;
import com.stumeet.server.member.domain.Member;
Expand All @@ -8,4 +9,6 @@ public interface MemberProfileUseCase {
void signup(Member member, MemberSignupCommand request);

void updateProfile(Member member, MemberUpdateCommand request);

MemberProfileResponse getProfileById(Long id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.stumeet.server.member.application.port.in.mapper;

import com.stumeet.server.member.adapter.in.web.response.MemberProfileResponse;
import com.stumeet.server.member.domain.Member;
import org.springframework.stereotype.Component;

@Component
public class MemberUseCaseMapper {

public MemberProfileResponse toProfileResponse(Member member) {
return MemberProfileResponse.builder()
.id(member.getId())
.image(member.getImage())
.nickname(member.getName())
.region(member.getRegion())
.profession(member.getProfession().getName())
.rank(member.getLevel().getRank().getName())
.experience(member.getLevel().getExperience())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

import com.stumeet.server.common.annotation.UseCase;
import com.stumeet.server.file.application.port.in.FileUploadUseCase;
import com.stumeet.server.member.adapter.in.web.response.MemberProfileResponse;
import com.stumeet.server.member.application.port.in.MemberProfileUseCase;
import com.stumeet.server.member.application.port.in.command.MemberProfileCommand;
import com.stumeet.server.member.application.port.in.command.MemberSignupCommand;
import com.stumeet.server.member.application.port.in.command.MemberUpdateCommand;
import com.stumeet.server.member.application.port.in.mapper.MemberUseCaseMapper;
import com.stumeet.server.member.application.port.out.MemberCommandPort;
import com.stumeet.server.member.application.port.out.MemberQueryPort;
import com.stumeet.server.member.domain.Member;
import com.stumeet.server.profession.application.port.in.ProfessionQueryUseCase;
import com.stumeet.server.profession.domain.Profession;
Expand All @@ -21,6 +24,9 @@ public class MemberProfileService implements MemberProfileUseCase {
private final ProfessionQueryUseCase professionQueryUseCase;
private final FileUploadUseCase fileUploadUseCase;
private final MemberCommandPort memberCommandPort;
private final MemberQueryPort memberQueryPort;
private final MemberUseCaseMapper memberUseCaseMapper;


@Override
public void signup(Member member, MemberSignupCommand request) {
Expand Down Expand Up @@ -61,4 +67,10 @@ public void updateProfile(Member member, MemberUpdateCommand request) {
memberCommandPort.update(member);
}

@Override
public MemberProfileResponse getProfileById(Long id) {
Member member = memberQueryPort.getById(id);
return memberUseCaseMapper.toProfileResponse(member);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@Transactional
public class LogoutFilterTest extends ApiTest {

@Container
Expand All @@ -54,11 +53,10 @@ class Logout {

@BeforeEach
void setUp() {
MemberJpaEntity entity = jpaMemberRepository.save(MemberStub.getMemberEntity());
redisTemplate.opsForValue()
.set(
JwtUtil.resolveToken(TokenStub.getMockAccessToken()),
jwtTokenProvider.generateRefreshToken(entity.getId())
jwtTokenProvider.generateRefreshToken(MemberStub.getMember().getId())
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WireMockTest(httpPort = 8089)
@Transactional
class OAuthAuthenticationFilterTest extends ApiTest {

@Container
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;


@Transactional
class MemberAuthApiTest extends ApiTest {

@Container
Expand All @@ -61,8 +60,7 @@ class tokenRenew {

@BeforeEach
void setUp() {
MemberJpaEntity entity = jpaMemberRepository.save(MemberStub.getMemberEntity());
refreshToken = jwtTokenProvider.generateRefreshToken(entity.getId());
refreshToken = jwtTokenProvider.generateRefreshToken(MemberStub.getMember().getId());
redisTemplate.opsForValue()
.set(TokenStub.getExpiredAccessToken(), refreshToken);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,35 @@

import com.stumeet.server.common.auth.model.AuthenticationHeader;
import com.stumeet.server.helper.WithMockMember;
import com.stumeet.server.member.adapter.out.persistence.JpaMemberRepository;
import com.stumeet.server.member.application.port.in.command.MemberUpdateCommand;
import com.stumeet.server.stub.MemberStub;
import com.stumeet.server.stub.TokenStub;
import com.stumeet.server.template.ApiTest;
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.mock.web.MockMultipartFile;
import org.springframework.test.web.servlet.request.RequestPostProcessor;
import org.springframework.transaction.annotation.Transactional;

import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName;
import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.*;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.restdocs.request.RequestDocumentation.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@Transactional
class MemberProfileApiTest extends ApiTest {

@Autowired
private JpaMemberRepository memberRepository;

@Nested
@DisplayName("내 프로필 수정")
class UpdateMyProfile {

private final String path = "/api/v1/members/me";

@BeforeEach
void setUp() {
memberRepository.save(MemberStub.getMemberEntity());
}

@Test
@WithMockMember
@DisplayName("[성공] 회원 프로필 수정에 성공한다.")
Expand Down Expand Up @@ -112,4 +100,33 @@ void invalidRequestTest() throws Exception {
)));
}
}

@Nested
@DisplayName("내 프로필 조회")
class GetMyProfile {

@Test
@WithMockMember
@DisplayName("[성공] 회원 프로필 조회에 성공한다.")
void successTest() throws Exception {
mockMvc.perform(get("/api/v1/members/me")
.header(AuthenticationHeader.ACCESS_TOKEN.getName(), TokenStub.getMockAccessToken()))
.andExpect(status().isOk())
.andDo(document("get-my-profile/success",
preprocessRequest(prettyPrint()),
preprocessResponse(prettyPrint()),
requestHeaders(headerWithName(AuthenticationHeader.ACCESS_TOKEN.getName()).description("서버로부터 전달받은 액세스 토큰")),
responseFields(
fieldWithPath("code").description("응답 상태"),
fieldWithPath("message").description("응답 메시지"),
fieldWithPath("data.id").description("회원 ID"),
fieldWithPath("data.image").description("프로필 이미지 URL"),
fieldWithPath("data.nickname").description("닉네임"),
fieldWithPath("data.region").description("지역"),
fieldWithPath("data.profession").description("분야 이름"),
fieldWithPath("data.rank").description("회원 레벨 - 랭크"),
fieldWithPath("data.experience").description("회원 레벨 - 경험치")
)));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;


@Transactional
class MemberValidApiTest extends ApiTest {

@Autowired
Expand All @@ -37,12 +36,6 @@ class MemberValidApiTest extends ApiTest {
class IsDuplicateNickname {

private final String path = "/api/v1/members/validate-nickname";
private MemberJpaEntity member;

@BeforeEach
void setUp() {
member = jpaMemberRepository.save(MemberStub.getMemberEntity());
}

@Test
@WithMockMember
Expand Down Expand Up @@ -96,7 +89,7 @@ void invalidRequestTest() throws Exception {
@WithMockMember
@DisplayName("[실패] 닉네임이 중복되면 검증에 실패합니다.")
void duplicateNicknameTest() throws Exception {
String nickname = member.getName();
String nickname = MemberStub.getMember().getName();
mockMvc.perform(get(path)
.header(AuthenticationHeader.ACCESS_TOKEN.getName(), TokenStub.getMockAccessToken())
.param("nickname", nickname))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.stumeet.server.member.application.service;

import com.stumeet.server.file.application.port.in.FileUploadUseCase;
import com.stumeet.server.member.adapter.in.web.response.MemberProfileResponse;
import com.stumeet.server.member.application.port.in.command.MemberUpdateCommand;
import com.stumeet.server.member.application.port.in.mapper.MemberUseCaseMapper;
import com.stumeet.server.member.application.port.out.MemberCommandPort;
import com.stumeet.server.member.application.port.out.MemberQueryPort;
import com.stumeet.server.member.domain.Member;
import com.stumeet.server.profession.application.port.in.ProfessionQueryUseCase;
import com.stumeet.server.stub.FileStub;
Expand All @@ -15,6 +18,7 @@
import org.mockito.InjectMocks;
import org.mockito.Mock;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;

Expand All @@ -33,6 +37,12 @@ class MemberProfileServiceTest extends UnitTest {
@Mock
private ProfessionQueryUseCase professionQueryUseCase;

@Mock
private MemberQueryPort memberQueryPort;

@Mock
private MemberUseCaseMapper memberUseCaseMapper;

@Nested
@DisplayName("멤버 프로필 업데이트")
class UpdateProfile {
Expand All @@ -54,4 +64,24 @@ void successTest() {
}
}

@Nested
@DisplayName("프로필 조회")
class GetProfileById {
@Test
@DisplayName("[성공] 멤버 프로필 조회에 성공한다.")
void successTest() {
Member member = MemberStub.getMember();
MemberProfileResponse want = MemberStub.getMemberProfileResponse(member);

given(memberQueryPort.getById(member.getId()))
.willReturn(member);
given(memberUseCaseMapper.toProfileResponse(member))
.willReturn(want);

MemberProfileResponse got = memberProfileService.getProfileById(member.getId());

assertThat(got).usingRecursiveComparison().isEqualTo(want);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@Transactional
class ProfessionQueryApiTest extends ApiTest {

@Nested
Expand Down
Loading

0 comments on commit 8f6e1d1

Please sign in to comment.