@DataJpaTest와 @AutoConfigureTestDatabase를 이용해 Repository 메서드를 단위 테스트해보자.
@DataJpaTest
기본적으로 JPA 관련 설정들을 로드한다. 기본적으로 인메모리 테스트 데이터베이스를 이용해 실제 데이터베이스를 이용하지 않고 사용하는 것이 가능하다.
또한, @Tranasactional을 가지고 있기 때문에 테스트가 진행된 이후 자동으로 롤백하는 것이 가능하다.
@AutoConfigureTestDatabase
애노테이션 뜻 그대로 테스트 데이터베이스의 구성정보를 자동으로 설정해주는 애노테이션이다. 이 또한, @DataJpaTest에 가지고 있다.
위에서 기본적으로 인메모리 테스트 데이터베이스를 이용한다고 한 부분이 @AutoConfigureTestDatabase의 기본 내장 DB 커넥션이 H2, HSQLDB와 같이 인메모리 DB로 되어있기 때문이다.
이번 테스트 코드에서는 실제 Database를 이용해서 테스트하기 위해서 Replace.NONE을 설정해서 코드를 작성했다.
Repository
테스트 코드를 작성할 Repository를 확인해보자.
@Repository
public interface EventRepository extends JpaRepository<Event, Long> {
// 이벤트 조회
Event findByEventId(Long eventId);
// 이벤트 저장
Event save(Event event);
// 이벤트 삭제
void deleteByEventId(Long eventId);
// 이벤트 리스트 조회(페이징)
@Query("SELECT e FROM Event e WHERE e.eventId < :eventId ORDER BY e.eventId DESC")
Slice<Event> findEventList(@Param("eventId") Long eventId, Pageable pageable);
}
테스트 코드
TestEntityManager를 이용해서 persis, find, flush와 같이 JPA의 실제 메서드를 테스트할 수 도 있다.
레포지토리 테스트 코드를 작성하는 도중 실제 DB를 이용하다 보니 저장 후 Auto Increment로 인한 엔티티의 Id를 가져오는 부분이 EntityManager를 이용하면 persist하고 가져올 수가 없었어서 아쉬운 대로 Repository에 저장한 save메서드를 사용해 테스트 코드를 작성했다.
Given(테스트 위한 사전 조건 및 Mocking 할 영역) , When(테스트를 할 영역), Then(테스트 이후 예상 결과와 실제 결과를 확인하는 영역)으로 구분 짓고 그에 맞는 코드를 작성했다.
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class EventRepositoryTest {
@Autowired
private EventRepository eventRepository;
@Autowired
private TestEntityManager em;
// TestEntityManager를 이용해 테스트
@Test
@DisplayName("이벤트 레포지토리 : 이벤트 조회")
void 이벤트조_조회하기() {
// given
Event event = testEventBuilder();
em.persist(event);
// when
Event findEvent = em.find(Event.class, event.getEventId());
// then
assertThat(event.getTitle()).isEqualTo(findEvent.getTitle());
}
// 실제 데이터베이스를 이용하는 경우 Auto Increment가 이미 데이터베이스에 적용되어 있기 때문에
@Test
@DisplayName("이벤트 레포지토리 : 이벤트 조회")
void 이벤트_조회() {
// given
Event savedEvent = eventRepository.save(testEventBuilder());
// when
Event findEvent = eventRepository.findByEventId(savedEvent.getEventId());
// then
assertThat(savedEvent.getEventId()).isEqualTo(findEvent.getEventId());
assertThat(savedEvent.getTitle()).isEqualTo(findEvent.getTitle());
assertThat(savedEvent.getEventDetail()).isEqualTo(findEvent.getEventDetail());
}
@Test
@DisplayName("이벤트 레포지토리 : 이벤트 등록")
void 이벤트_등록() {
// given
Event event = testEventBuilder();
// when
Event savedEvent = eventRepository.save(event);
// then
assertThat(savedEvent.getTitle()).isEqualTo(event.getTitle());
assertThat(savedEvent.getEventDetail()).isEqualTo(event.getEventDetail());
}
@Test
@DisplayName("이벤트 레포지토리 : 이벤트 삭제")
void 이벤트_삭제() {
// given
Event savedEvent = eventRepository.save(testEventBuilder());
// when
eventRepository.deleteByEventId(savedEvent.getEventId());
// then
Event findEvent = eventRepository.findByEventId(savedEvent.getEventId());
assertThat(findEvent).isNull();
}
@Test
@DisplayName("이벤트 레포지토리 : 이벤트 리스트 조회")
void 이벤트_리스트_조회() {
// given
eventRepository.save(testEventBuilder());
eventRepository.save(testEventBuilder());
eventRepository.save(testEventBuilder());
// when
Slice<Event> findEventList = eventRepository.findEventList(10000L, PageRequest.of(0, 2));
// then
assertThat(findEventList.getSize()).isEqualTo(2);
}
// 이벤트 엔티티 생성
private static Event testEventBuilder() {
return Event.builder()
.eventId(1L)
.title("title")
.eventDetail("eventDetail")
.regYmd(LocalDateTime.now())
.eventStart(LocalDate.now())
.eventEnd(LocalDate.now().plusWeeks(1))
.build();
}
}
테스트가 모두 성공되는 것을 확인할 수 있다.
'Backend > Spring Boot' 카테고리의 다른 글
[API 고급] 컬렉션 조회 최적화 (0) | 2022.07.12 |
---|---|
[API 개발 고급] 지연 로딩과 조회 성능 최적화 (0) | 2022.07.07 |
API 개발 기본 간단 정리 (0) | 2022.07.07 |
도메인 개발 팁 간단 정리 (0) | 2022.07.05 |
RestTemplate (0) | 2022.07.01 |