Repository 테스트 코드를 작성하다 겪게 된 문제이다.
단순히 입력된 값이 올바르게 저장되었는지만 테스트 해보고 말았는데,
JPA의 Persistent Context를 고려하지 못한 테스트 방법이었다.
간략하게 이해하자면, DB IO Overload를 방지하기 위해,
JPA는 Persistent Context라는 일종의 버퍼를 만들어 두고,
어떠한 기준으로 버퍼에 쌓인 데이터를 DB에 적용한다.
DB에 다이렉트로 뭔가를 하는게 아니기 때문에,
그 완전성과 무결성을 보장할 수 없다는 의미임.
그러니까, 테스트코드를 작성할 때도
saved, willBeSaved로 비교하는 방식은 잘못되었다는 이야기.
적합한 방식은 이와 같다.
1. 내가 오늘 저지른 경범죄 코드.
@Test
void of(){
// public static User of(Long id, String username, String password) {
// GIVEN
User willBeSaved = User.of(1L, "testNickname", "string");
// WHEN
User saved = userApiRepository.save(willBeSaved);
User found = userApiRepository.findById(saved.getId()).get();
// THEN
assertEquals(found.getId(), willBeSaved.getId());
assertEquals(found.getNickname(), willBeSaved.getNickname());
assertEquals(found.getFcmToken(), willBeSaved.getFcmToken());
}
}
이런식으로 코드를 작성했는데,
물론 findById를 통해 DB에 반영된 이후의 것을 접근하니까
Persistent Context로 인해 발생하는 문제들은 검증될 것이란 보장은 있다.
다만 아쉬운 점은,
Test Code의 목적은, 어디서 오류가 발생했는지 알고싶은 것이 그 목적인데,
위 코드의 경우, 만약 findById가 실패했을 경우?
그냥 에러처리가 나기 때문에, 어떤 문제가 발생했는지 찾는데 약간의 수고로움이 들어간다.
2. 비교적 이상적인 코드
@Test
void of() {
// GIVEN
Post willBeSaved = Post.of(1L, PostCategory.INQUIRY, "Test입니다", "Test입니다");
// WHEN
Post saved = postApiRepository.save(willBeSaved);
Optional<Post> found = postApiRepository.findById(saved.getId());
// THEN
assertTrue(found.isPresent());
assertEquals(saved, found.get());
}
findById에서 null을 반환했을 때를 고려해, found 자체를 Optional로 두고 있다.
가벼운 예외처리를 적용할 수도 있고, 향후 개발자가 save의 문제를 해결할 때 이점이 있다는 부분에서
이 코드가 더 적합한 코드로 이해된다.
이제 Service layer의 테스트코드를 공부해보자.
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!