Skip to content
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.livable.server.member.controller;

import com.livable.server.core.response.ApiResponse;
import com.livable.server.member.dto.MemberResponse;
import com.livable.server.member.service.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RequiredArgsConstructor
@RestController
public class MemberController {

private final MemberService memberService;

@GetMapping("/api/members")
public ResponseEntity<ApiResponse.Success<MemberResponse.MyPageDTO>> myPage() {

Long memberId = 1L; // TODO: JWT 구현 후 토큰에서 값 추출 예정
MemberResponse.MyPageDTO myPageDTO = memberService.getMyPageData(memberId);

return ApiResponse.success(myPageDTO, HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.livable.server.member.domain;

import com.livable.server.core.exception.ErrorCode;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public enum MemberErrorCode implements ErrorCode {

MEMBER_NOT_EXIST(HttpStatus.BAD_REQUEST, "존재하지 않는 회원 정보입니다.");

private final HttpStatus httpStatus;
private final String message;
}
Empty file.
24 changes: 24 additions & 0 deletions src/main/java/com/livable/server/member/dto/MemberResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.livable.server.member.dto;

import lombok.*;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class MemberResponse {

@Getter
@Builder
public static class MyPageDTO {

String memberName;
String companyName;
Integer pointValance;

public static MyPageDTO from(MyPageProjection myPageProjection) {
return MyPageDTO.builder()
.memberName(myPageProjection.getMemberName())
.companyName(myPageProjection.getCompanyName())
.pointValance(myPageProjection.getPointValance())
.build();
}
}
}
14 changes: 14 additions & 0 deletions src/main/java/com/livable/server/member/dto/MyPageProjection.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.livable.server.member.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

@Getter
@AllArgsConstructor
public class MyPageProjection {

String memberName;
String companyName;
Integer pointValance;
}
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
package com.livable.server.member.repository;

import com.livable.server.entity.Member;
import com.livable.server.member.dto.MyPageProjection;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.Optional;

public interface MemberRepository extends JpaRepository<Member, Long> {

@Query("SELECT new com.livable.server.member.dto.MyPageProjection(m.name, c.name, p.balance) " +
"FROM Member m " +
"INNER JOIN Company c ON c.id = m.company.id " +
"INNER JOIN Point p ON p.member.id = m.id " +
"WHERE m.id = :memberId")
Optional<MyPageProjection> findMemberCompanyPointData(@Param("memberId") Long memberId);
}
Empty file.
27 changes: 27 additions & 0 deletions src/main/java/com/livable/server/member/service/MemberService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.livable.server.member.service;

import com.livable.server.core.exception.GlobalRuntimeException;
import com.livable.server.member.domain.MemberErrorCode;
import com.livable.server.member.dto.MemberResponse;
import com.livable.server.member.dto.MyPageProjection;
import com.livable.server.member.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.Optional;

@RequiredArgsConstructor
@Service
public class MemberService {

private final MemberRepository memberRepository;

public MemberResponse.MyPageDTO getMyPageData(Long memberId) {

Optional<MyPageProjection> myPageProjectionOption = memberRepository.findMemberCompanyPointData(memberId);
MyPageProjection myPageProjection = myPageProjectionOption.orElseThrow(()
-> new GlobalRuntimeException(MemberErrorCode.MEMBER_NOT_EXIST));

return MemberResponse.MyPageDTO.from(myPageProjection);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.livable.server.member.controller;

import com.livable.server.member.dto.MemberResponse;
import com.livable.server.member.service.MemberService;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentMatchers;
import org.mockito.Mockito;
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.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

@WebMvcTest(MemberController.class)
class MemberControllerTest {

@Autowired
private MockMvc mockMvc;

@MockBean
private MemberService memberService;

@Nested
@DisplayName("마이페이지 컨트롤러 단위 테스트")
class MyRestaurantReview {

@DisplayName("성공")
@Test
void success_Test() throws Exception {
// Given
String uri = "/api/members";

MemberResponse.MyPageDTO mockDTO = MemberResponse.MyPageDTO.builder()
.memberName("TestName")
.companyName("TestCompany")
.pointValance(200)
.build();

Mockito.when(memberService.getMyPageData(ArgumentMatchers.anyLong()))
.thenReturn(mockDTO);

// When
// Then
mockMvc.perform(MockMvcRequestBuilders.get(uri)
.accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.data").exists());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.livable.server.member.service;

import com.livable.server.core.exception.GlobalRuntimeException;
import com.livable.server.member.dto.MemberResponse;
import com.livable.server.member.dto.MyPageProjection;
import com.livable.server.member.repository.MemberRepository;
import org.junit.jupiter.api.Assertions;
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.ArgumentMatchers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.Optional;

@ExtendWith(MockitoExtension.class)
class MemberServiceTest {

@Mock
private MemberRepository memberRepository;

@InjectMocks
private MemberService memberService;

@Nested
@DisplayName("마이페이지 서비스 단위 테스트")
class MyRestaurantReview {

@DisplayName("성공")
@Test
void success_Test() {
// Given
Long memberId = 1L;
String memberName = "TestName";
String companyName = "TestCompany";
Integer pointValance = 200;

MyPageProjection mockResult
= new MyPageProjection(memberName, companyName, pointValance);

Mockito.when(memberRepository.findMemberCompanyPointData(ArgumentMatchers.anyLong()))
.thenReturn(Optional.of(mockResult));

// When
MemberResponse.MyPageDTO actual = memberService.getMyPageData(memberId);

// Then
Assertions.assertAll(
() -> Assertions.assertEquals(memberName, actual.getMemberName()),
() -> Assertions.assertEquals(companyName, actual.getCompanyName()),
() -> Assertions.assertEquals(pointValance, actual.getPointValance())
);
}

@DisplayName("실패 - 유효하지 않은 회원 정보")
@Test
void failure_Test_InvalidMember() {
// Given
Long memberId = 1L;

// When
Mockito.when(memberRepository.findMemberCompanyPointData(ArgumentMatchers.anyLong()))
.thenReturn(Optional.empty());

// Then
Assertions.assertThrows(GlobalRuntimeException.class, () ->
memberService.getMyPageData(memberId));
}
}
}