기능이 원하는 대로 동작하는지 알아보기 위해 검증을 해야 한다. 이럴 때 테스트 케이스를 사용한다.
회원 리포지토리 테스트 케이스 작성
개발한 기능을 실행해서 테스트 할 때 자바의 main 메서드를 통해서 실행하거나, 웹 애플리케이션의 컨트롤러를 통해서 해당 기능을 실행한다. 이러한 방법은 준비하고 실행하는데 오래 걸리고, 반복 실행하기 어렵기 때문에 여러 테스트를 한 번에 실행하기 어렵다.(단점) 자바는 JUnit 이라는 프레임워크로 테스트를 실행해서 이러한 문제를 해결했다.
test - java - hello.hellospring(package) - repository(package) - MemoryMemberRepositoryTest(calss)를 하나 만들었다.
class MemoryMemberRepositoryTest {
//검사할 class 이름
MemoryMemberRepository repository = new MemoryMemberRepository();
@Test
public void save(){
Member member = new Member();
member.setName("spring");
repository.save(member);
Member result = repository.findById(member.getId()).get();
//System.out.println("result = " + (result == member));
//Assertions.assertEquals(member, result);
assertThat(member).isEqualTo(result);
//org.assertj.core.api
}
@Test
public void findByName(){
Member member1 = new Member();
member1.setName("spring1");
repository.save(member1);
//shift+F6 == rename
Member member2 = new Member();
member2.setName("spring1");
repository.save(member2);
Member result = repository.findByName("spring1").get();
assertThat(result).isEqualTo(member1);
}
@Test
public void findAll(){
Member member1 = new Member();
member1.setName("spring1");
repository.save(member1);
Member member2 = new Member();
member2.setName("spring1");
repository.save(member2);
List<Member> result = repository.findAll();
assertThat(result.size()).isEqualTo(2);
}
}
순서대로 메소드를 실행하면 성공하지만, class를 통해 한번에 실행할 경우 (한 번에 검사할 경우)
위처럼 오류를 보인다. 한 번에 실행할 경우 메서드 실행 순서가 보장되지 않아(메서드 별로 따로 동작) 객체에 의도한 값이 저장되지 않았기 때문이다. 이를 방지하기 위해 test를 할 때마다 저장된 값을 비워줘야 한다.
이전에 만들었던 MemoryMemberRepository class에 아래 메소드를 추가한다.
다시 MemoryMemberRepositoryTest로 돌아와서 어노테이션을 통해 위에서 만들었던 메서드를 호출한다.
이럼 순서 상관없이 test 할 수 있다.
지금은 개발을 다 끝내놓은 뒤, 검증했다. 그러나 먼저 틀을 만들어 놓은 뒤(TestClass를 먼저 만들어 놓은 뒤), 구현할 class를 작성할 수도 있다. 이렇게 순서를 뒤집는 것을 TDD: 테스트 주도 개발이라고 한다.
회원 서비스 개발
main - service(package) - MemberSevice(class)를 생성.
package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import java.util.List;
import java.util.Optional;
public class MemberService { // 비지니스 메소드
private final MemberRepository memberRepository = new MemoryMemberRepository();
//회원가입
public Long join(Member member){
//같은 이름이 있는 중복 회원은 안돼
validateDuplicateMember(member); // 중복 회원 검증
memberRepository.save(member);
return member.getId();
}
//ctrl + alt + M
private void validateDuplicateMember(Member member) {
memberRepository.findByName(member.getName())
.ifPresent(m -> {
throw new IllegalStateException("이미 존재하는 회원입니다.");
//Null일 가능성이 있는 경우 Optional로 한번 감싼뒤 반환. ifPresent 같은 함수 사용가능.
});
}
//전체 회원 조회
public List<Member> findMembers() {
return memberRepository.findAll();
}
public Optional<Member> findOne(Long memberId){
return memberRepository.findById(memberId);
}
}
기능 별로 메서드를 작성했다. 이제 이걸 테스트 해봐야 겠다.
회원 서비스 테스트
편하게 test하는 다른 방법이 있다. class 이름에 대고 ctrl + shift + T를 누르면
create new test를 누른 뒤 testing library는 JUnit5를 선택하고 ok를 누른다. 그럼 아래처럼 자동으로 test code가 생성된다.
이때, test 코드의 같은 경로로 생성된다. DI(Dependency Injection)을 위해 MemberService class를 아래 처럼 바꿔준뒤
위에서 생성한 테스트 코드를 아래처럼 작성했다.
package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemoryMemberRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;
class MemberServiceTest {
MemberService memberService;
MemoryMemberRepository memberRepository;
@BeforeEach
public void beforeEach(){// 실행전 MemoryMemberRepository 객체 생성후 이걸 넣어줌
memberRepository = new MemoryMemberRepository();
memberService = new MemberService(memberRepository);
}
@AfterEach // 어떤 메서드가 실행되고 난 후 매번 실행되는 메서드란 표시
public void afterEach() {
memberRepository.clearStore();
}
@Test
void 회원가입() {
//given : 이런 상황이 주어졌다.
Member member = new Member();
member.setName("hello");
//when : 이걸 실행했을 때
Long saveId = memberService.join(member);
//then : 이런 결과가 나와야해.
Member findMember = memberService.findOne(saveId).get();
assertThat(member.getName()).isEqualTo(findMember.getName());
}
@Test
public void 중복_회원_예외(){
//given
Member member1 = new Member();
member1.setName("spring");
Member member2 = new Member();
member2.setName("spring");
//when
memberService.join(member1);
IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));
assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
// try{
// memberService.join(member2);
// fail();
// }catch (IllegalStateException e){
// assertThat(e. getMessage()).isEqualTo("이미 존재하는 회원입니다.");
// }
//then
}
@Test
void findMembers() {
}
@Test
void findOne() {
}
}
'Spring > 스프링 입문' 카테고리의 다른 글
[김영한::스프링 입문] 회원 관리 예제 - 웹 MVC 개발 (0) | 2023.02.19 |
---|---|
[김영한::스프링 입문] 스프링 빈과 의존관계 - 컴포넌트 스캔과 자동 의존관계 설정 (0) | 2023.02.17 |
[김영한::스프링 입문] 회원 관리 예제 1 (0) | 2023.02.11 |
[김영한::스프링 입문] 스프링 웹 개발 기초 (2) | 2023.02.10 |
[김영한::스프링 입문] View 환경설정 (0) | 2023.02.09 |