일일히 테스트 코드를 작성하지 않고 클래스를 선택한 후 ctrl + shift + T를 눌러주면 바로 테스트 코드가 작성된다.

테스트를 생성할 메소드를 선택해주고 ok를 누르면 테스트 코드가 생성된다.


우선 회원가입 테스트 코드를 작성해보자
여기서 주석처리 된 given when then은 각 코드에 어떤 값이 들어오고 어떤 동작을 하고 그 결과를 출력하는 과정을 코드 가동성을 위해 나눠서 표시했음을 의미한다.
우선 회원가입 테스트 코드를 작성해보자

member 객체를 생성해준 후 setName 메서드를 사용해 이름값을 spring으로 저장해줬다.
이어서 memberService의 join 메서드를 사용해서 Long 타입의 saveId에 저장해줬고 결과적으로 member의 이름값을 호출해 비교했을때 True를 반환하게 된다.
다음으로 중복 회원 예외 케이스를 테스트해보자.

해당 기능을 구현할 수 있는 방법은 두가지가 있다
try와 catch를 사용해 구현하는 방법과 assert와 람다를 사용해서 구현하는 방법
try catch보다 assert와 람다를 사용하는 방법이 더 좋다고 하는데 그 이유는 다음과 같다고 한다.
이유
- 가독성: 람다식을 사용하면 예외 처리 코드가 짧고 간결해집니다. 예외 처리 코드를 보다 쉽게 이해할 수 있고, 코드의 구조가 더 명확해집니다.
- 테스트 메서드 내부에서 예외 처리: 람다식을 사용하면 예외 처리 코드를 직접 테스트 메서드 내부에 작성할 수 있습니다. 이는 테스트 메서드의 의도를 분명하게 표현하고, 테스트 코드를 더 간결하게 유지할 수 있도록 도와줍니다.
- 예외 발생 시점 제어: 람다식을 사용하면
assertThrows
메서드 내에서 예외를 기대하는 구간에만 예외 처리 코드가 적용됩니다. 예외 처리 코드를 특정 부분에 집중시킴으로써 예외가 발생했을 때의 테스트 결과를 정확하게 확인할 수 있습니다.
- 예외 타입 검증:
assertThrows
메서드의 첫 번째 인자로 예상되는 예외 타입을 명시함으로써, 코드 상에서 발생한 예외와 예상한 예외가 동일한지를 검증할 수 있습니다. 이를 통해 테스트의 정확성을 보장할 수 있습니다.
try catch 방법은 우선 memberService의 join 메서드를 통해 member2 객체를 넘겨준다. join 메서드의 중복 여부를 판별하는 validateDuplicateMember에서 예외 처리를 발생시켜 IllegalStateException을 throw 하고 이를 전달받았을 시 예외가 발생했다는 안내 메세지인 “이미 존재하는 회원입니다.”를 리턴하게 되고 이를 비교해 예외처리가 정상적으로 발생했다는 사실을 확인해볼 수 있다.
assert와 람다를 사용해서 구현하는 방법은 우선 assertThrows 메서드를 호출하여 예외 처리를 실행할 것이다. 여기서 assertThrows 메서드는 총 2가지의 인자를 전달받는다.
첫번째 인자로는 IllegalStateException.class 를 전달하고 두번째 인자로는 람다식으로 실행된 memberService.join(member2) 넣어준다. 여기서 만약 예상 예외였던 IllegalStateException가 발생한다면 해당 예외 객체를 e 변수에 할당한다.
그리고 해당 예외처리가 가지고 있는 메세지와 예상 메세지를 비교한 뒤 값이 같으면 True를 리턴한다.
그리고 저번 repository testcode와 마찬가지로 AfterEach를 설정해준다.

여기서 BeforeEach를 설정해준 이유는 하나의 class에서 다른 repository를 선언해 테스트를 진행 할 경우 해당 repository에서 static 메서드가 삭제될 시 완전히 다른 결과가 도출될수도 있다고 하는데 아직은 이해가 살짝 어려운것같다 그래서 gpt 선생에서 여쭤봤다.
gpt 선생 왈
주어진 코드는
MemberServiceTest
클래스에서BeforeEach
어노테이션을 사용하여 초기화 작업을 수행하는 부분입니다. 이 작업을 하는 이유는 다음과 같습니다:- 테스트 환경 설정:
BeforeEach
어노테이션은 각각의 테스트 메서드가 실행되기 전에 실행되는 메서드를 지정합니다. 이 메서드에서는 테스트 환경을 설정하고, 테스트에 필요한 객체들을 초기화합니다.
- 의존성 주입:
memberRepository
와memberService
는 테스트할 대상인MemberService
클래스와 그에 필요한 의존 객체입니다.BeforeEach
메서드에서memberRepository
와memberService
를 초기화하고 연결함으로써 의존성 주입(Dependency Injection)을 구현합니다.
- 격리된 테스트 환경: 각각의 테스트 메서드가 독립적인 테스트 환경에서 실행되기 위해 초기화 작업이 필요합니다.
BeforeEach
메서드를 사용하면 테스트 간에 객체 상태가 공유되지 않고 독립적으로 실행되는 것을 보장합니다.
- 코드 중복 최소화:
BeforeEach
메서드를 사용하면 여러 테스트 메서드에서 반복되는 초기화 작업을 중복해서 작성할 필요가 없습니다. 대신 한 곳에서 초기화를 수행하므로 코드 중복을 최소화할 수 있습니다.
따라서
BeforeEach
메서드를 사용하여 초기화 작업을 수행함으로써 테스트 환경 설정, 의존성 주입, 격리된 테스트 환경, 코드 중복 최소화 등의 이점을 얻을 수 있습니다. 이는 테스트를 보다 효율적으로 작성하고 유지보수할 수 있는 기반을 제공합니다.주어진 코드에서 수행되는 작업은 다형성과 인터페이스를 적용시키는 작업과 유사합니다.
- 다형성:
memberRepository
와memberService
변수들은 해당하는 인터페이스 타입인MemoryMemberRepository
와MemberService
의 인스턴스를 참조합니다. 이를 통해 다형성 개념을 활용하고 있습니다.MemoryMemberRepository
는MemberRepository
인터페이스를 구현하고,MemberService
는MemberRepository
인터페이스를 의존으로 받는 것으로 추측됩니다. 이로써MemberService
클래스는MemberRepository
인터페이스에 의존하며, 실제 구현은 런타임에 결정됩니다. 이는 인터페이스를 통한 추상화와 결합도의 감소를 가능하게 합니다.
- 의존성 주입(Dependency Injection):
BeforeEach
메서드에서memberRepository
를MemoryMemberRepository
의 인스턴스로 생성하고, 이를memberService
에 주입하여 의존성 주입을 수행합니다. 이를 통해MemberService
클래스는 외부에서MemberRepository
구현체를 주입받아 사용하므로, 결합도를 낮추고 유연성을 확보할 수 있습니다.
따라서 해당 작업은 자바의 다형성과 인터페이스를 적용시키는 작업과 유사하며, 객체 지향 프로그래밍의 원칙에 따라 인터페이스를 사용하여 의존성을 추상화하고, 다형성을 활용하여 유연하고 확장 가능한 코드를 작성하고 있습니다.
- 테스트 환경 설정:
전체 코드
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.assertThrows;
class MemberServiceTest {
MemberService memberService;
MemoryMemberRepository memberRepository;
@BeforeEach
public void beforEach(){
memberRepository = new MemoryMemberRepository();
memberService = new MemberService(memberRepository);
}
@AfterEach
public void afterEach(){
memberRepository.clearStore();
}
@Test
void 회원가입() {
// given
Member member = new Member();
member.setName("spring");
// 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' 카테고리의 다른 글
스프링 DB 접근 기술 (0) | 2023.07.11 |
---|---|
회원 서비스 개발 (0) | 2023.07.06 |
회원 리포지토리 테스트 케이스 작성 (0) | 2023.07.04 |
비즈니스 요구사항 정리 (0) | 2023.07.04 |
회원 도메인과 리포지토리 만들기 (0) | 2023.07.04 |