이 포스트는 김영한 강사님의 [실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발] 을 바탕으로 작성되었습니다.
섹션 4. 회원 도메인 개발
순서
1) 회원 리포지토리 개발
2) 회원 서비스 개발
3) 회원 기능 테스트
1) 회원 리포지토리 개발
package jpabook.jpashop.repository;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jpabook.jpashop.domain.Member;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
@RequiredArgsConstructor
public class MemberRepository {
private final EntityManager em;
public void save(Member member) {
em.persist(member);
}
public Member findOne(Long id) {
return em.find(Member.class, id);
}
public List<Member> findAll(){
return em.createQuery("select m from Member m", Member.class)
.getResultList();
}
public List<Member> findByName(String name){
return em.createQuery("select m from Member m where m.name = :name", Member.class)
.setParameter("name", name)
.getResultList();
}
}
2) 회원 서비스 개발
package jpabook.jpashop.service;
import jpabook.jpashop.domain.Member;
import jpabook.jpashop.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@Transactional(readOnly = true) //트랜잭션, 영속성 컨텍스트
//readOnly=true : 데이터의 변경이 없는 읽기 전용 메서드에 사용, 영속성 컨텍스트를 플러시 하지 않으므로
//약간의 성능 향상(읽기 전용에는 다 적용)
@RequiredArgsConstructor
public class MemberService {
/**
* @Autowired
* MemberRepository memberRepository;
* 생성자 Injection 많이 사용, 생성자가 하나면 생략 가능
*/
private final MemberRepository memberRepository;
/**
* public MemberService(MemberRepository memberRepository){
* this.memberRepository = memberRepository;
* }
* lombok의 @RequiredArgsConstructor을 이용하면 생략할 수 있다.
*/
//회원 가입
@Transactional
public Long join(Member member) {
validateDuplicateMember(member);
memberRepository.save(member);
return member.getId();
}
private void validateDuplicateMember(Member member) {
List<Member> findMembers = memberRepository.findByName(member.getName());
if (!findMembers.isEmpty()) {
throw new IllegalStateException("이미 존재하는 회원입니다.");
}
}
//회원 전체 조회
public List<Member> findMembers(){
return memberRepository.findAll();
}
public Member findOne(Long memberId) {
return memberRepository.findOne(memberId);
}
}
3) 회원 기능 테스트
package jpabook.jpashop.service;
import jakarta.persistence.EntityManager;
import jpabook.jpashop.domain.Member;
import jpabook.jpashop.repository.MemberRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import static org.junit.Assert.*;
@RunWith(SpringRunner.class) //스프링과 테스트 통합
@SpringBootTest //스프링부트 띄우고 테스트 (이게 없으면 @Autowired 다 실패)
@Transactional //반복 가능한 테스트 지원, 각각의 테스트를 실행할 때마다 트랜잭션을 시작하고 테스트가 끝나면 트랜잭션을 강제로 롤백함
public class MemberServiceTest {
@Autowired MemberService memberService;
@Autowired MemberRepository memberRepository;
@Autowired EntityManager em;
@Test
public void 회원가입() throws Exception{
//given
Member member = new Member();
member.setName("kim");
//when
Long savedId = memberService.join(member);
//then
assertEquals(member, memberRepository.findOne(savedId));
}
@Test(expected = IllegalStateException.class)
public void 중복_회원_예외() throws Exception{
//given
Member member1 = new Member();
member1.setName("kim");
Member member2 = new Member();
member2.setName("kim");
//when
memberService.join(member1);
memberService.join(member2);
//then
fail("예외가 발생해야 한다.");
}
}
테스트 케이스 작성 고수 되는 마법: Given, When, Then
(http://martinfowler.com/bliki/GivenWhenThen.html)
이 방법이 필수는 아니지만 이 방법을 기본으로 해서 다양하게 응용하는 것을 권장한다.
테스트 케이스를 위한 설정
테스트는 케이스 격리된 환경에서 실행하고, 끝나면 데이터를 초기화하는 것이 좋다. 그런 면에서 메모리 DB를 사용하
는 것이 가장 이상적이다.
추가로 테스트 케이스를 위한 스프링 환경과, 일반적으로 애플리케이션을 실행하는 환경은 보통 다르므로 설정 파일을
다르게 사용하자. 다음과 같이 간단하게 테스트용 설정 파일을 추가하면 된다.
" test/resources/application.yml "
이제 테스트에서 스프링을 실행하면 이 위치에 있는 설정 파일을 읽는다.
(만약 이 위치에 없으면 src/resources/application.yml 을 읽는다.)
스프링 부트는 datasource 설정이 없으면, 기본적을 메모리 DB를 사용하고, driver-class도 현재 등록된 라이브러를
보고 찾아준다. 추가로 ddl-auto 도 create-drop 모드로 동작한다. 따라서 데이터소스나, JPA 관련된 별도의 추
가 설정을 하지 않아도 된다.
'Spring > Spring Boot' 카테고리의 다른 글
섹션 7. 웹 계층 개발 [실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발] (1) | 2024.01.01 |
---|---|
섹션 6. 주문 도메인 개발 [실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발] (2) | 2023.12.07 |
섹션 5. 상품 도메인 개발 [실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발] (0) | 2023.12.07 |
섹션 2,3. 도메인 분석 설계, 구현 준비 [실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발] (0) | 2023.12.07 |
섹션 1. 프로젝트 환경설정 [실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발] (0) | 2023.12.06 |