반응형
고민 내용
- Spring Data JPA 기반의 Repository를 테스트 할 때, @SpringBootTest 와 @DataJpaTest 중 어떤 어노테이션을 사용하는 것이 좋을까?
소스 코드: ChatBotRoomRepositoryTest
- 시간 차이를 보다 자세히 확인하기 위해, BeforeEach에서 9996개의 ChatBotRoom 데이터를 DB에 생성한 다음, 테스트를 수행하였다.
- SpringBootTest 어노테이션을 사용하는 경우, @SpringBootTest와 @Transactional를 사용하고, @AutoConfigureTestDatabase와 @DataJpaTest를 주석 처리한다.
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) // To use MySQL
@ActiveProfiles("test")
@DataJpaTest
//@SpringBootTest
//@Transactional
class ChatBotRoomRepositoryTest {
@Autowired
private ChatBotRoomRepository chatBotRoomRepository;
@BeforeEach
void setUp() {
List<ChatBotRoom> rooms = new ArrayList<>();
for (int i = 5; i <= 10000; i++) {
ChatBotRoom room = createChatBotRoom("room-" + i, "i" + i, "r" + i);
rooms.add(room);
}
chatBotRoomRepository.saveAll(rooms);
}
@Test
@DisplayName("roomId로 챗봇 대화방을 조회한다")
void findChatBotRoomByRoomId() {
// given
String targetRoomId = "room-1";
ChatBotRoom room1 = createChatBotRoom(targetRoomId, "i1", "r1");
ChatBotRoom room2 = createChatBotRoom("room-2", "i2", "r2");
chatBotRoomRepository.saveAll(List.of(room1, room2));
// when
Optional<ChatBotRoom> result = chatBotRoomRepository.findChatBotRoomByRoomId(targetRoomId);
// then
// 조회 검증
assertThat(result.get().getRoomId()).isEqualTo(targetRoomId);
}
@Test
@DisplayName("사용자 닉네임으로 방 전체를 조회한다.")
void findAllByInitiatorNickname() {
// given
String targetNickname = "i1";
ChatBotRoom room1 = createChatBotRoom("room-1", targetNickname, "r1");
ChatBotRoom room2 = createChatBotRoom("room-2", targetNickname, "r2");
ChatBotRoom room3 = createChatBotRoom("room-3", "i2", "r2");
chatBotRoomRepository.saveAll(List.of(room1, room2, room3));
// when
List<ChatBotRoom> rooms = chatBotRoomRepository.findAllByInitiatorNickname(targetNickname);
// then
assertThat(rooms).hasSize(2)
.extracting("roomId", "initiatorNickname", "recipientNickname")
.containsExactlyInAnyOrder(
tuple("room-1", targetNickname, "r1"),
tuple("room-2", targetNickname, "r2")
);
}
@Test
@DisplayName("roomId로 채팅방을 삭제한다")
void deleteChatBotRoomByRoomId() {
// given
String targetRoomId = "room-1";
ChatBotRoom room1 = createChatBotRoom(targetRoomId, "i1", "r1");
ChatBotRoom room2 = createChatBotRoom("room-2", "i2", "r2");
chatBotRoomRepository.saveAll(List.of(room1, room2));
// when
chatBotRoomRepository.deleteChatBotRoomByRoomId(targetRoomId);
// then
// assertThat(chatBotRoomRepository.findAll().size()).isEqualTo(1);
assertThat(chatBotRoomRepository.findChatBotRoomByRoomId(targetRoomId)).isEmpty();
}
private ChatBotRoom createChatBotRoom(String roomId,
String initiatorNickname,
String recipientNickname) {
return ChatBotRoom.builder()
.roomId(roomId)
.initiatorNickname(initiatorNickname)
.recipientNickname(recipientNickname)
.build();
}
}
실행 결과
@SpringBootTest & @Transactional
@DataJpaTest
- 약 300ms 정도 속도로 DataJpaTest가 빠른 것을 확인할 수 있다.
- 여기서는 테스트 메서드가 3개이고 데이터가 약 10,000개였으나, 추후 테스트 메서드와 데이터가 모두 많아진다면, 시간 차이가 훨씬 커질 것으로 예상할 수 있다.
내가 생각한 차이의 원인
- https://docs.spring.io/spring-boot/docs/1.4.2.RELEASE/reference/html/boot-features-testing.html
- 위의 공식 문서를 참고하였음.
- @DataJpaTest can be used if you want to test JPA applications. By default it will configure an in-memory embedded database, scan for @Entity classes and configure Spring Data JPA repositories. Regular @Component beans will not be loaded into the ApplicationContext.
- Spring Boot provides a @SpringBootTest annotation which can be used as an alternative to the standard spring-test @ContextConfiguration annotation when you need Spring Boot features. The annotation works by creating the ApplicationContext used in your tests via SpringApplication.
- 정리하면, @SpringBootTest 는 @ComponentScan 내의 모든 Bean 객체가 ApplicationContext에 올라간후 실행된다.
- 반면, @DataJpaTest 는 Entity와 JPA Repository와 관련된 것들만 ApplicationContext에 올라간 후 실행된다. 또한 기본적으로 In-memory인 h2-database 기반으로 동작한다.
결론
- RepositoryTest의 경우, @SpringBootTest 보다 @DataJpaTest 를 사용하는 것이 성능상에서 조금 더 유리하다. 왜나하면 ApplicationContext의 모든 Bean 객체를 올리지 않기 때문이다.
반응형
'멘질멘질] 2023 졸업 프로젝트' 카테고리의 다른 글
Spring Boot] 406 Not Acceptable 오류 (0) | 2023.06.13 |
---|---|
Junit5] 테스트에서 *.properties 정보 읽어오지 못하는 경우 해결 방법 (0) | 2023.06.13 |
Spring Boot] CORS 해결 (0) | 2023.06.09 |
Spring Boot] 프로젝트를 진행하는 과정에서 원칙 정리 (0) | 2023.06.09 |
GitHub Action, Docker, EC2를 사용한 Spring Boot 프로젝트 배포 자동화 (0) | 2023.06.09 |