쌓고 쌓다
회원 리포지토리 테스트 케이스 작성 본문
개발한 기능을 테스트할 때 main 메소드를 통해 실행하거나 웹 애플리케이션의 컨트롤러로 기능을 실행한다.
이 방법은 준비하고 실행하는데 오래 걸리고, 반복 실행하기 어렵고, 여러 테스트를 한 번에 실행하기 어렵다.
그래서 자바의 JUnit이라는 프레임워크로 테스트를 실행한다.
src/test/java 하위 폴더에 똑같은 패키지를 생성.
save 메소드 테스트
public class MemoryMemberRepositoryTest {
MemberRepository repository = new MemoryMemberRepository();
@Test
public void saveTest() {
Member member = new Member();
member.setName("name1");
repository.save(member);
// 반환값 optinal이라 get으로 꺼냄
Member result = repository.findById(member.getId()).get();
System.out.println("result = " + (member == result));
//계속 글자를 출력하여 볼 순 없다. -> Assertions 사용
Assertions.assertEquals(member, result);
}
}
Assertions org.assertj.core.api를 요즘은 사용한다.
Assertions.assertThat(member).isEqualTo(result);
인터페이스 객체 생성?
MemberRepository repository = new MemoryMemberRepository();
MemberRepository는 인터페이스이다.
위와 같이 인터페이스는 객체 생성은 불가능하지만 레퍼런스는 만들 수 있다.
여기에 구현 객체를 생성하여 지정할 수 있다.
구현 객체를 생성하여 지정하지 않고 익명 구현 객체를 사용할 수도 있다.
(참조: https://hyuntaekhong.github.io/blog/java-basic20/)
findByName 메소드 테스트
public class MemoryMemberRepositoryTest {
MemberRepository repository = new MemoryMemberRepository();
@Test
public void findByName() {
Member member1 = new Member();
member1.setName("name1");
Member member2 = new Member();
member2.setName("name2");
repository.save(member1);
repository.save(member2);
Member result = repository.findByName("name1").get();
assertThat(result).isEqualTo(member1);
}
}
각각의 테스트는 독립적
클래스 레벨에서 테스트를 돌리면 테스트 메소들을 모두 테스트한다.
모두 동시에 테스트를 돌렸더니 각각 잘 돌아가던 메소드가 실패가 발생한다.
각 메소드에서 생성하여 리포지토리에 넣은 객체들이 그대로 남아있기에
멤버를 생성하고 테스트하는데 문제가 발생한 것이다.
그래서 각각의 테스트는 독립적으로 실행되게 할 필요가 있다.
=> 테스트 메소드 실행 순서는 랜덤. 순서에 의존적으로 만들지 말자.
MemoryMemberRepository.java
public class MemoryMemberRepository implements MemberRepository{
private static Map<Long, Member> store = new HashMap<>();
...
// 추가된 clearStore 메소드
public void clearStore() {
store.clear();
}
...
}
MemoryMemberRespository 클래스에 Map을 비워주는 메소드를 하나 만들자.
이제 테스트 코드에 @AfterEach를 사용하여 메모리DB를 비워주는 작업을 하는 메소드를 작성한다.
@AfterEach는 각 테스트가 종료될때 마다 이 메소드를 실행한다.
앞서 인터페이스에 바로 객체를 생성하여 지정하였는데.
이러면 인터페이스에 해당 메소드가 존재하지 않아 사용이 불가능하므로 아래처럼
객체의 레퍼런스 또한 인터페이스가 아닌 클래스로 수정을 해야 함.
// 수정전 : MemberRepository repository = new MemoryMemberRepository();
MemoryMemberRepository repository = new MemoryMemberRepository();
findAll 메소드 테스트
public class MemoryMemberRepositoryTest {
MemoryMemberRepository repository = new MemoryMemberRepository();
@AfterEach
public void afterEach() {
repository.clearStore();
}
@Test
public void findAll() {
Member member1 = new Member();
member1.setName("name1");
Member member2 = new Member();
member2.setName("name2");
repository.save(member1);
repository.save(member2);
List<Member> result = repository.findAll();
assertThat(result.size()).isEqualTo(2);
}
}
MemoryMemberRepository를 개발하고 테스트를 작성하는 방식이 아닌 뒤집어서
테스트 클래스를 먼저 작성하고 MemoryMemberRepository를 만들 수도 있다.
-> 테스트 주도 개발이라고 TDD 방식임.
'프로그래밍 > spring' 카테고리의 다른 글
회원 서비스 테스트 ( 의존성 주입, 예외 테스트 코드 ) (0) | 2023.05.07 |
---|---|
회원 서비스 클래스 작성 (0) | 2023.05.02 |
회원 도메인과 리포지토리 만들기 (0) | 2023.04.29 |
[Spring] API (0) | 2023.03.22 |
[Spring] MVC와 템플릿 엔진 with @RequestParam (0) | 2023.03.18 |