회원 도메인과 리포지토리 만들기
@Override
public Optional<Member> findById(Long id) {
return Optional.ofNullable(store.get(id));//null 반환될 수 있으면 Optional로 감싸서 반환
}
return값으로 null이 반환될 수 있어서 반환 타입을 Optional로 감싸서 반환한다.
회원 리포지토리 테스트 케이스 작성
MemoryMemberRepositoryTest
@Test
public void save() {
Member member = new Member();
member.setName("spring");
repository.save(member);
Member result = repository.findById(member.getId()).get(); //get으로 꺼내는게 좋은 방법은 아니지만 테스트라서 이렇게 해도 됨
//1. Assertions.assertEquals(member,result); [검증] 두 객체가 동일한지
assertThat(member).isEqualTo(result); //2
}
MemoryMemberRepository에서 만든 save 메소드를 테스트한다.
검증 방법은 Assertions.assertEquals()와 좀 더 간단한 Assertions.asserThat()이 있다.
두번째의 경우 커서 위치에서 alt+enter 누르고 Add on-demand static import~ 를 누르면 Assertions가 static import 가 된다.
import static org.assertj.core.api.Assertions.*;
테스트는 순서 보장이 되지 않는다. 순서랑 상관없이 따로 동작하도록 만들어야 한다.
순서에 의존적으로 설정하면 안된다.

findAll()이 마지막에 작성됐어도 첫번째로 실행되었다.
순서에 의존적이지 않게 설정하려면 테스트 끝날때마다 리포지토리를 지워야한다. 즉 데이터를 클리어해야한다. 저장소나 공용데이터를 지워야한다.
MemoryMemberRepository
public void clearStore() {
store.clear(); //store 싹 비우기
}
MemoryMemberRepositoryTest
public class MemoryMemberRepositoryTest {
MemoryMemberRepository repository = new MemoryMemberRepository();
@AfterEach
public void afterEach() { //테스트가 한번 실행되고 나서 리포지토리를 싹 다 지움
repository.clearStore();
}
save 테스트하고 afterEach 실행, findByName 테스트 하고 afterEach 실행
이런식으로 각 테스트를 한 후 afterEach를 실행해서 리포지토리를 싹 지워야한다.
회원서비스 개발
public class MemberService {
private final MemberRepository memberRepository = new MemoryMemberRepository();
/**
* 회원가입
*/
public Long join(Member member){
//같은 이름이 있는 중복 회원X
Optional<Member> result = memberRepository.findByName(member.getName());
result.ifPresent(m->{ //ifPresent : null이 아니라 값이 있으면 로직이 동작함
//Optional 안에 멤버 객체가 있음 그래서 Optional 통해서 여러 메서드를 사용할 수 있음
//Optional로 감싼 덕분에 가능한 일
throw new IllegalStateException("이미 존재하는 회원입니다.");
});
memberRepository.save(member);
return member.getId();
}
}
Optional<Member> result = memberRepository.findByName(member.getName());
Optional을 바로 반환하는 것을 권장하지 x
//같은 이름이 있는 중복 회원X
memberRepository.findByName(member.getName())
.ifPresent(m->{
throw new IllegalStateException("이미 존재하는 회원입니다.");
});
memberRepository.findByName(member.getName()); 얘가 반환한게 Optional타입의 result니까 바로 이런식으로 감 이런 경우 메소드로 뽑는 것이 좋다
메소드 뽑는 단축키 컨트롤+시프트+알트+T 이후 extract method 클릭
Service 클래스 네이밍은 비지니스 용어를 쓰는 것이 좋다 리포지토리는 개발스럽게 단순한 용어 사용
회원 서비스 테스트
테스트 바로 생성 단축키 컨트롤+시프트+T

변수명 한꺼번에 바꾸기 시프트 + f6
테스트는 예외를 다루는게 더 중요하다. 일부러 예외 발생하기
1.try-catch문
@Test
public void 중복_회원_예외() {
//given
Member member1 = new Member();
member1.setName("spring");
Member member2 = new Member();
member2.setName("spring");
//when
memberService.join(member1);
try {
memberService.join(member2);
fail();
}catch (IllegalStateException e){
assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
}
//then
}
2.정공법
@Test
public void 중복_회원_예외() {
//given
Member member1 = new Member();
member1.setName("spring");
Member member2 = new Member();
member2.setName("spring");
//when
memberService.join(member1);
assertThrows(IllegalStateException.class, () -> memberService.join(member2));
//인자 해석 : 이 예외가 터져야하고, 이 로직을 따를때
}
예외메세지까지 확인하는 테스트는 아래와 같이 하면 된다.
//when
memberService.join(member1);
IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));//이 예외가 터져야하고, 이 로직을 따를때
assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
MemoryMemberRepository memberRepository = new MemoryMemberRepository();
@AfterEach
public void afterEach(){
memberRepository.clearStore();
}
데이터가 계속 누적되면서 리포지토리에 쌓이니까 데이터 날리는 코드가 필요함
이전에 실행했던거 또 실행하는 단축키 시프트+f10
MemberServiceTest
MemoryMemberRepository memberRepository = new MemoryMemberRepository();
MemberService
private final MemberRepository memberRepository = new MemoryMemberRepository();
MemberServiceTest를 테스트할때 생성한 객체와 MemberService의 객체를 모았을때 새로운 객체 2개가 생성되었다
MemberServiceTest에서 생성한 인스턴스는 다른 인스턴스라서 내용물이 달라질 수 있다.
같은 인스턴스를 생성하도록 만들어야한다.
해결법
MemberService
public class MemberService {
private final MemberRepository memberRepository;
public MemberService(MemberRepository memberRepository) { //멤버리포지토리를 외부에서 넣어주게 생성함 (DI)
this.memberRepository = memberRepository;
}
MemberServiceTest
class MemberServiceTest {
MemberService memberService;
MemoryMemberRepository memberRepository;
//멤버서비스 만들때 메모리멤버리포지토리를 넣어준다
@BeforeEach
public void beforeEach(){
memberRepository = new MemoryMemberRepository();
memberService = new MemberService(memberRepository);
}
'Springboot' 카테고리의 다른 글
| 김영한 스프링 입문 섹션 5.회원 관리 예제-웹 MVC 개발 정리 (0) | 2024.03.08 |
|---|---|
| 김영한 스프링 입문 섹션 4.컴포넌트 스캔과 자동 의존관계 설정 정리 (1) | 2024.03.08 |
| 김영한 스프링 입문:섹션2 스프링 웹 개발 기초 정리 (1) | 2024.03.05 |
| String 을 LocalDate 바꾸는 법 (0) | 2024.01.20 |
| Spring boot 구글 소셜로그인 OAuth 로그인 구현 (0) | 2024.01.10 |