- 컨트롤러 : 웹 MVC의 컨트롤러 역할 (해당되는 요청에 연결)
- 서비스 : 핵심 비즈니스 로직을 구현하는 곳
- 레포지토리 : 실제 DB에 접근하는 여러 기능을 구현하는 곳
- 도메인 : DB에 저장되는 실제 객체 (DTO역할)
ex) [ 사용자의 회원가입 절차 ]
1.[POST] http://localhost:3000/signup
: 사용자가 입력한 정보를 post로 전송2.
Controller
에서 해당하는서비스
에 연결3.
서비스
에서 회원가입 절차 수행
3-1. user라는도메인
을 가져온 뒤 객체에 받은 정보를 담는다.
3-2. 레포지토리에 있는signup()
메소드를 실행시켜 실제 DB에 저장
(signup()
에 정보를 담은도메인
을 전달)
: 개발한 기능을 맞게 구현했는지 실행하기 위해 사용하는 코드
- 만약 테스트 할 때 마다 main 메서드를 실행하고, 컨트롤러를 통해 해당 기능을 수행한다면 매우 번거롭고, 한번에 여러개의 기능을 점검하기 어렵다
--> Java는 JUnit이라는 프레임워크로 테스트를 실행한다
[ MemberService의 테스트 코드 ]
package hello.hellospring.service; import hello.hellospring.domain.Member; import hello.hellospring.repository.MemoryMemberRepository; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.util.Optional; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.junit.jupiter.api.Assertions.*; class MemberServiceTest { MemberService memberService; MemoryMemberRepository memberRepository; // MemoryMemberRepository를 서비스에서 생성하지 않고 테스트 코드 시작 전에 생성해서 전달! (DI) @BeforeEach public void beforeEach(){ memberRepository = new MemoryMemberRepository(); memberService = new MemberService(memberRepository); } @AfterEach public void afterEach(){ memberRepository.clearStore(); } // Test는 한글로 바꾸어도 좋다! 우리가 보기 좋기 때문 // 보통 테스트 코드는 given -> when -> then을 따르게 되니까 주석으로 표시도 많이함! @Test void 회원가입() { //given - 이런 상황이 주어지면 Member member = new Member(); member.setName("spring"); //when - 실행했을 때 Long saveId = memberService.join(member); //then - 결과가 나와야 한다 Member findMember = memberService.findOne(saveId).get(); Assertions.assertThat(member.getName()).isEqualTo(findMember.getName()); } @Test void 중복_회원_예외(){ // given Member member1 = new Member(); member1.setName("spring"); Member member2 = new Member(); member2.setName("spring"); // when // try ~ catch로 예외를 잡을수도 있지만, assertThrow로 잡는 더 좋은 방법이 있다. /* memberService.join(member1); try{ memberService.join(member2); fail(); }catch(IllegalStateException e){ assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다."); }*/ memberService.join(member1); IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2)); assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다"); // then } }
given ~ when ~ then
으로로 초기에는 테스트코드를 작성하는 것이 좋다(보통 어떤 데이터가 주어지고 / 기능을 수행할 때 / 어떻게 되는지 공통)
- assertj에서 제공하는 것들이 사용된다
Assertion.assertThat().isEqualTo()
: Then에서 값 비교에 사용
- Java의 Optional 문법도 알아 둘 필요가 있다.
.ifPresent()
: 값이 있으면 ()실행.get()
: Optinal로 value를 감싼 것이기 때문에 value에 접근하기 위해 사용