본문 바로가기

SPRING/Spring 활용

[스프링부트| 스프링부트와 JPA 활용 1 | 웹 애플리케이션 개발 | 회원 도메인 개발] 회원 기능 테스트

@RunWith(SpringRunner.class) // 스프링 부트 테스트를 위한 JUnit 러너 설정
@SpringBootTest // 스프링 부트 애플리케이션 컨텍스트를 로드하는 테스트를 위한 설정
@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 saveId = memberService.join(member); // 멤버 서비스를 통해 멤버 가입 처리

        //then
        assertEquals(member, memberRepository.findOne(saveId)); // 저장된 멤버가 리포지토리에서 정상적으로 조회되는지 검증
    }

    @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

Given-When-Then은 소프트웨어 개발에서 테스트 케이스를 작성할 때 널리 사용되는 패턴입니다. 이 패턴은 행동 주도 개발(Behavior-Driven Development, BDD)에서 유래했으며, 테스트의 구조를 명확하게 하여 각 테스트의 목적과 동작을 이해하기 쉽게 만듭니다. 각 구성 요소의 역할은 다음과 같습니다:

Given

  • 목적: 테스트를 수행하기 위한 초기 상태를 설정합니다. 이 단계에서는 테스트에 필요한 데이터, 객체, 변수 등의 초기화를 포함합니다.
  • 예시: 사용자 정보 설정, 테스트에 필요한 파일을 로드, 테스트 환경 구성 등.

When

  • 목적: 테스트의 주요 행위 또는 조작을 수행합니다. 이 단계에서 실제로 테스트하고자 하는 기능이 실행됩니다.
  • 예시: 특정 함수 호출, 이벤트 발생, 조건 트리거 등.

Then

  • 목적: When 단계에서의 결과를 검증합니다. 이 단계에서는 기대하는 결과가 실제로 도출되었는지 확인합니다.
  • 예시: 결과 데이터 검증, 예외 발생 확인, 출력값이 예상과 일치하는지 확인 등.

이 패턴은 테스트 케이스를 명확하고 이해하기 쉽게 작성하는 데 도움을 주며, 개발자가 의도한 특정 기능이 기대대로 작동하는지 검증하는 데 중점을 둡니다. 또한, 이 패턴을 사용하면 코드의 읽기 쉽고 유지보수하기 쉬운 구조를 갖출 수 있으며, 다른 개발자나 이해 관계자가 테스트 케이스를 더 쉽게 이해할 수 있습니다.

Given-When-Then 패턴은 테스트 자동화뿐만 아니라 문서화된 테스트 시나리오에서도 유용하게 활용됩니다. 이로 인해 BDD 프레임워크에서는 이 패턴을 기본 구조로 채택하여, 사용자 스토리와 요구 사항을 명확하게 연결짓는 데 도움을 줍니다.

 

@Test(expected = Exception.class)

JUnit 테스트 프레임워크에서 @Test(expected = Exception.class) 어노테이션은 테스트 메소드를 실행할 때 특정 예외가 발생할 것으로 예상되는 경우에 사용됩니다. 이 어노테이션을 사용하면 테스트가 해당 예외를 발생시키면 테스트가 성공한 것으로 간주됩니다. 반대로 예상한 예외가 발생하지 않으면 테스트는 실패합니다.

사용 방법

@Test(expected = IllegalStateException.class)는 IllegalStateException이 해당 테스트 메소드 실행 중에 발생할 것으로 예상할 때 사용됩니다. 예를 들어, 어떤 메소드가 특정 상황에서 IllegalStateException을 발생시키도록 설계되었다면, 이를 테스트하기 위해 expected 속성을 사용할 수 있습니다.

주요 이점

  • 간결성: 예외 처리 코드를 작성할 필요 없이 한 줄의 어노테이션으로 예외 발생을 테스트할 수 있습니다.
  • 명확성: 테스트 코드를 읽는 사람에게 어떤 예외가 발생할 것으로 예상되는지 명확하게 알려줍니다.
  • 효율성: 복잡한 try-catch 로직 없이 예외 발생 여부를 간단히 검증할 수 있습니다.

주의할 점

  • 정확한 예외 타입: expected 속성에 지정된 예외 타입이 정확히 일치해야 합니다. 상위 타입이나 하위 타입의 예외는 이 기준을 만족시키지 않습니다.
  • 단일 예외 검증: 이 방법은 한 번에 하나의 예외만 검증할 수 있습니다. 여러 예외를 동시에 검증하려면 별도의 접근 방식이 필요합니다.
  • 예외 발생 지점: 예외가 어디서 발생했는지 정확히 알 수 없으므로, 테스트 대상 코드의 특정 부분에서만 예외가 발생하는지 확인하고 싶다면, 이 방법보다는 try-catch와 함께 fail() 메소드를 사용하는 것이 더 적절할 수 있습니다.

@Test(expected = ...) 어노테이션은 간단하게 예외 발생을 검증할 때 유용하지만, 보다 세밀한 예외 처리 검증이 필요한 경우에는 다른 접근 방법을 고려해야 할 수도 있습니다.