Slice Test - 데이터 액세스 계층

seongmin·2022년 11월 16일
0

Spring

목록 보기
37/38
post-thumbnail

데이터 액세스 계층 테스트 시에는 아래와 같은 한가지 규칙을 지키는 것이 좋다.

  • DB의 상태를 테스트 케이스 실행 이전으로 되돌려서 깨끗하게 만든다.
public class DataAccessLayerTest {
		@Test
		public void testA() {
				// (1-1) 데이터가 DB에 잘 저장되는지를 테스트하기 위해 한 건의 데이터를 DB에 저장
				// (1-2) DB에 잘 저장되었는지 DB에서 조회해서 결과를 확인
		}

		@Test
		public void testB() {
				// (2-1) 데이터가 DB에서 잘 조회 되는지를 테스트하기 위해 DB에서 조회
		}
}

DataAccessLayerTest 클래스 내의 전체 테스트 케이스를 실행했을 때, testA() 부터 실행된다면, 결과는 passed 일 것이다.

하지만, 다시 실행했을 때, testB() 가 먼저 실행된다면 이미 테스트 케이스에 입력으로 전달한 WHERE 조건의 값이 고정된 상태에서 DB에 조회를 했는데 원하는 결과 값이 없기 때문에 테스트 결과는 “failed”일 것이다.

첫번째 경우는 testA() 가 먼저 실행이 되었기 때문에 테스트 결과가 “passed”이지만 두 번째 경우는 testA() 먼저 실행이 되지 않았기 때문에 INSERT 된 데이터가 없기 때문이다.

이처럼 테스트 케이스는 여러 개의 테스트 케이스를 일괄적으로 실행 시키더라도 각각의 테스트 케이스에 독립성이 보장되어야 한다.

이러한 문제가 발생하지 않도록 하는 가장 좋은 방법은 테스트 케이스 하나가 실행될 때, 해당 테스트 케이스에서 사용했던 데이터가 DB에 저장이 되어 있는 상태라면 테스트 케이스 실행 종료 시점에 저장되었던 데이터를 삭제해 주는 것이다.

테스트

  • 회원 정보 저장 테스트
@DataJpaTest   // (1)
public class MemberRepositoryTest {
    @Autowired
    private MemberRepository memberRepository;   // (2)

    @Test
    public void saveMemberTest() {
        // given  (3)
        Member member = new Member();
        member.setEmail("hgd@gmail.com");
        member.setName("홍길동");
        member.setPhone("010-1111-2222");

        // when  (4)
        Member savedMember = memberRepository.save(member);

        // then  (5)
        assertNotNull(savedMember); // (5-1)
        assertTrue(member.getEmail().equals(savedMember.getEmail()));
        assertTrue(member.getName().equals(savedMember.getName()));
        assertTrue(member.getPhone().equals(savedMember.getPhone()));
    }
}
  1. Spring에서 데이터 액세스 계층을 테스트 하기 위한 가장 핵심적인 방법은 바로 (1)과 같이 @DataJpaTest애너테이션이다.

    @DataJpaTest 애너테이션을 테스트 클래스에 추가함으로써, MemberRepository의 기능을 정상적으로 사용하기 위한 Configuration을 Spring이 자동으로 해주게 된다.

    @DataJpaTest 애너테이션은 @Transactional 애너테이션을 포함하고 있기 때문에 하나의 테스트 케이스 실행이 종료되는 시점에 데이터베이스에 저장된 데이터는 rollback 처리된다.

    즉, 여러 개의 테스트 케이스를 한꺼번에 실행 시켜도 하나의 테스트 케이스가 종료될 때마다 데이터베이스의 상태가 초기 상태를 유지한다는 것이다.

  1. (2)에서 테스트 대상 클래스인 MemberRepository를 DI 받는다.

  2. (3)에서 테스트 할 회원 정보 데이터(member)를 준비한다.

  3. (4)에서 회원 정보를 저장한다.

  4. (5)에서 회원 정보가 잘 저장되었는지 검증(Assertion)한다.

    먼저 (5-1)과 같이 회원 정보를 정상적으로 저장한 뒤에 리턴 값으로 반환 된 Member 객체(savedMember)가 null이 아닌지를 검증한다.

    나머지는 리턴 값으로 반환 된 Member 객체(savedMember)의 필드 들이 테스트 데이터와 일지하는지 검증한다.


  • 회원 정보 조회 테스트
@DataJpaTest
public class MemberRepositoryTest {
    ...
		...

    @Test
    public void findByEmailTest() {
        // given (1)
        Member member = new Member();
        member.setEmail("hgd@gmail.com");
        member.setName("홍길동");
        member.setPhone("010-1111-2222");

        // when 
        memberRepository.save(member);  // (2)
        Optional<Member> findMember = memberRepository.findByEmail(member.getEmail()); // (3)

				// then (4)
        assertTrue(findMember.isPresent()); // (4-1)
        assertTrue(findMember.get().getEmail().equals(member.getEmail())); // (4-2)
    }
}
  1. (1)에서 테스트 할 회원 정보 데이터(member)를 준비한다.

  2. (2)에서 회원 정보를 저장한다.

  3. 이번에는 (2)에서 저장 후, 리턴되는 Member 객체를 이용하는 것이 아니라 (2)에서 저장한 회원 정보 중에서 이메일에 해당되는 회원 정보를 잘 조회하는지 테스트하기 위해 (3)과 같이 findByEmail() 로 회원 정보를 조회하고 있다.

  4. (4)에서 회원 정보의 조회가 정상적으로 이루어지는지 검증(Assertion)한다.

    먼저 (4-1)과 같이 조회된 회원 정보가 null이 아닌지를 검증한다.

    (4-2)에서 조회한 회원의 이메일 주소와 테스트 데이터의 이메일과 일치하는지 검증한다.


Spring JDBC 환경에서는 @JdbcTest , Spring Data JDBC 환경에서는 @DataJdbcTest 를 사용하면 손쉽게 데이터 액세스 계층에 대한 테스트를 진행할 수 있다.

0개의 댓글