diff --git a/plan/4.3. study_plan-week-3-summary.md b/plan/4.3. study_plan-week-3-summary.md index 8771a72..ce83b7d 100644 --- a/plan/4.3. study_plan-week-3-summary.md +++ b/plan/4.3. study_plan-week-3-summary.md @@ -8,12 +8,12 @@ - **3.1.4.** ManyToOne, OneToMany 사용 - **3.2.** Spring Boot 테스트 코드 작성 - **3.2.1.** 단위 테스트 (Unit Test) 작성 - - **3.2.1.1.** 테스트 관점에서의 Request, Response DTO 클래스 작성의 필요성 + - MockMvc 사용 + - 테스트 관점에서의 Request, Response DTO 클래스 작성의 필요성 - **3.2.2.** 통합 테스트 (Integration Test) 작성 - - **3.2.3.** MockMvc 사용 - **3.3.** RESTful API 설계 및 구현 - **3.3.1.** RESTful API 기본 원칙 - - **3.3.1.1.** 데이터 전송 관점에서의 Request, Response DTO 클래스 작성 + - 데이터 전송 관점에서의 Request, Response DTO 클래스 작성의 필요성 - **3.3.3.** API 예외 처리 - **3.3.4.** Spring Validation 사용 - **3.3.5.** Converter 사용 diff --git a/spring-boot/src/main/java/com/mpc/springboot/Application.java b/spring-boot/src/main/java/com/mpc/springboot/Application.java index 51b0be6..99cf2ca 100644 --- a/spring-boot/src/main/java/com/mpc/springboot/Application.java +++ b/spring-boot/src/main/java/com/mpc/springboot/Application.java @@ -4,7 +4,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; -@EnableJpaAuditing @SpringBootApplication public class Application { diff --git a/spring-boot/src/main/java/com/mpc/springboot/config/audit/AuditingConfiguration.java b/spring-boot/src/main/java/com/mpc/springboot/config/audit/AuditingConfiguration.java new file mode 100644 index 0000000..7277ac0 --- /dev/null +++ b/spring-boot/src/main/java/com/mpc/springboot/config/audit/AuditingConfiguration.java @@ -0,0 +1,9 @@ +package com.mpc.springboot.config.audit; + +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; + +@EnableJpaAuditing +@Configuration +public class AuditingConfiguration { +} diff --git a/spring-boot/src/main/java/com/mpc/springboot/member/application/dto/MemberResponse.java b/spring-boot/src/main/java/com/mpc/springboot/member/application/dto/MemberResponse.java new file mode 100644 index 0000000..b6af37d --- /dev/null +++ b/spring-boot/src/main/java/com/mpc/springboot/member/application/dto/MemberResponse.java @@ -0,0 +1,17 @@ +package com.mpc.springboot.member.application.dto; + +import com.mpc.springboot.member.domain.entity.Member; +import com.mpc.springboot.member.domain.vo.MemberCode; +import com.mpc.springboot.member.domain.vo.MemberName; +import lombok.*; + +@Getter +@RequiredArgsConstructor(access = AccessLevel.PROTECTED) +public class MemberResponse { + private final MemberCode code; + private final MemberName name; + + public static MemberResponse from(Member member) { + return new MemberResponse(member.getCode(), member.getName()); + } +} diff --git a/spring-boot/src/main/java/com/mpc/springboot/member/application/service/MemberService.java b/spring-boot/src/main/java/com/mpc/springboot/member/application/service/MemberService.java index 948efae..d720de7 100644 --- a/spring-boot/src/main/java/com/mpc/springboot/member/application/service/MemberService.java +++ b/spring-boot/src/main/java/com/mpc/springboot/member/application/service/MemberService.java @@ -3,6 +3,7 @@ import jakarta.transaction.Transactional; import org.springframework.stereotype.Service; +import com.mpc.springboot.member.application.dto.MemberResponse; import com.mpc.springboot.member.domain.entity.Member; import com.mpc.springboot.member.domain.exception.MemberNotFoundException; import com.mpc.springboot.member.domain.repository.MemberRepository; @@ -15,9 +16,10 @@ public class MemberService { private final MemberRepository memberRepository; - public Member getMemberBy(MemberCode code) { - return memberRepository.findMemberBy(code) - .orElseThrow(MemberNotFoundException::new); + public MemberResponse getMemberBy(MemberCode code) { + Member member = memberRepository.findMemberBy(code) + .orElseThrow(MemberNotFoundException::new); + return MemberResponse.from(member); } @Transactional diff --git a/spring-boot/src/main/java/com/mpc/springboot/member/presentation/controller/MemberRestController.java b/spring-boot/src/main/java/com/mpc/springboot/member/presentation/controller/MemberRestController.java index 3bce35d..2cab449 100644 --- a/spring-boot/src/main/java/com/mpc/springboot/member/presentation/controller/MemberRestController.java +++ b/spring-boot/src/main/java/com/mpc/springboot/member/presentation/controller/MemberRestController.java @@ -2,6 +2,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import com.mpc.springboot.member.application.dto.MemberResponse; import com.mpc.springboot.member.application.service.MemberService; import com.mpc.springboot.member.domain.entity.Member; import com.mpc.springboot.member.domain.vo.MemberCode; @@ -15,7 +16,7 @@ public class MemberRestController { private final MemberService memberService; @GetMapping("/{code}") - public ResponseEntity getMemberBy(@PathVariable MemberCode code) { + public ResponseEntity getMemberBy(@PathVariable MemberCode code) { return ResponseEntity.ok(memberService.getMemberBy(code)); } diff --git a/spring-boot/src/test/java/com/mpc/springboot/member/presentation/controller/MemberRestControllerTest.java b/spring-boot/src/test/java/com/mpc/springboot/member/presentation/controller/MemberRestControllerTest.java new file mode 100644 index 0000000..87bd87e --- /dev/null +++ b/spring-boot/src/test/java/com/mpc/springboot/member/presentation/controller/MemberRestControllerTest.java @@ -0,0 +1,53 @@ +package com.mpc.springboot.member.presentation.controller; + +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import com.mpc.springboot.member.application.dto.MemberResponse; +import com.mpc.springboot.member.application.service.MemberService; +import com.mpc.springboot.member.domain.entity.Member; +import com.mpc.springboot.member.domain.repository.MemberRepository; +import com.mpc.springboot.member.domain.vo.MemberCode; +import com.mpc.springboot.member.domain.vo.MemberName; +import com.mpc.springboot.shared.AbstractControllerTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(MemberRestController.class) +class MemberRestControllerTest extends AbstractControllerTest { + + @MockitoBean + private MemberService memberService; + + /** + * @see MemberRestController#getMemberBy(MemberCode) + */ + @DisplayName("회원 조회: 회원 코드로 조회") + @Test + void getMemberBy() throws Exception { + // given + MemberCode code = MemberCode.of("M0000003"); + MemberName name = MemberName.of("John", "Doe"); + Member member = Member.of(code, name); + MemberResponse memberResponse = MemberResponse.from(member); + given(memberService.getMemberBy(any())).willReturn(memberResponse); + + // when & then + mockMvc.perform(get("/api/v1/members/{code}", code.getValue())) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code.value").value(code.getValue())) + .andExpect(jsonPath("$.name.firstName").value(name.getFirstName())) + .andExpect(jsonPath("$.name.lastName").value(name.getLastName())) + .andExpect(jsonPath("$.name.fullName").value(name.getFullName())); + + } + + @Test + void createMember() { + } +} \ No newline at end of file diff --git a/spring-boot/src/test/java/com/mpc/springboot/shared/AbstractControllerTest.java b/spring-boot/src/test/java/com/mpc/springboot/shared/AbstractControllerTest.java new file mode 100644 index 0000000..1397490 --- /dev/null +++ b/spring-boot/src/test/java/com/mpc/springboot/shared/AbstractControllerTest.java @@ -0,0 +1,14 @@ +package com.mpc.springboot.shared; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.test.web.servlet.MockMvc; + +@WebMvcTest +@AutoConfigureMockMvc +public abstract class AbstractControllerTest { + + @Autowired + protected MockMvc mockMvc; +}