게시판의 대댓글 관련 테스트 코드를 작성하다가 NullPointException이 발생했다.
1. 우선 테스트하고자는 코드를 살펴보자
- 서비스 코드
@Slf4j
@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class BoardSubCommentService {
private final BoardSubCommentRepository boardSubCommentRepository;
private final UserRepository userRepository;
private final BoardCommentRepository boardCommentRepository;
/**
* 대댓글을 저장한다.
*/
@Transactional
public BoardSubCommentDto saveBoardSubComment(Long boardCommentId, String loginId, String content) {
if (content.isEmpty() || content == null) {
throw new ProfileApplicationException(ErrorCode.NOT_VALID_BOARD_SUB_COMMENT_CONTENT);
}
// 1. 댓글정보를 가져온다.
BoardComment boardComment = boardCommentRepository.findById(boardCommentId)
.orElseThrow(() -> new ProfileApplicationException(ErrorCode.BOARD_COMMENT_NOT_FOUND));
// 2. 유저정보를 가져온다.
User user = userRepository.findUserByLoginId(loginId)
.orElseThrow(() -> new ProfileApplicationException(ErrorCode.USER_NOT_FOUND));
// 3. 저장할 대댓글 엔티티를 생성한다. 대댓글을 적게될 상위 댓글 엔티티와 대댓글을 작성한 유저와 대댓글 내용을 통해 만들어 준다.
BoardSubComment boardSubComment = BoardSubComment.of(boardComment, user, content);
return BoardSubCommentDto.fromEntity(boardSubCommentRepository.save(boardSubComment));
}
}
- 작성한 테스트 코드
@DisplayName("[bad]-대댓글에 null이거나 공백 문자를 적어서 저장했을때는 예외가 발생한다.")
@Test
void saveBoardSubCommentException3() {
//given
User savedUser = createUser();
Board savedBoard = createBoard(savedUser, "test");
BoardComment savedBoardComment = createBoardComment(savedBoard, savedUser);
Long boardCommentId = 1L;
String loginId = "wlsdks123";
//when & then
//junit5의 assertAll과 assertJ의 assertThatThrownBy를 함께 사용했다.
assertAll(
() -> assertThatThrownBy(() -> boardSubCommentService.saveBoardSubComment(boardCommentId, loginId, ""))
.isInstanceOf(ProfileApplicationException.class),
() -> assertThatThrownBy(() -> boardSubCommentService.saveBoardSubComment(boardCommentId, loginId, null))
.isInstanceOf(ProfileApplicationException.class)
);
}
2. 에러 상황 설명
- 아래와 같은 에러가 발생했다.
- 뜬금없이 if문으로 예외처리를 했던 content값에서 NPE -> NullPointException가 발생한 것이다..!
3. 에러 수정
- 처음에는 null을 서비스 코드에서 못잡아내는줄 알고 서비스 코드로 돌아가서 다시 if문을 확인했다.
if (content.isEmpty() || content == null) {
throw new ProfileApplicationException(ErrorCode.NOT_VALID_BOARD_SUB_COMMENT_CONTENT);
}
- 근데 뭔가 이상한데...? 처음에는 바로 알아채지 못했다.
코드를 잘보면 content.isEnpty()가 먼저 비교대상이 된다.
이 코드의 문제점은 다음과 같다.
- 여기서 NullPointerException이 발생하는 이유는 대댓글의 내용인 content 변수의 값을 검사하는 로직인 isEmpty() 메서드를 먼저 호출하려고 시도하기 때문이다.
- if문 안을 보면 코드에서는 content.isEmpty()를 먼저 확인하고 그 다음에 content == null을 확인하고 있다. 따라서 content가 null인 경우 isEmpty() 메서드를 호출한다면 메서드를 통해 검증할때 당연히 content에 값이 없으니 NullPointerException가 발생한다.
즉, 순서가 잘못된 것이었다.. 기본적인 것인데 이런 실수를 하다니.. 생각을 못했다.
덕분에 테스트 코드가 이렇게 중요하다는걸 또 느꼈다.
2023.08.16 - [Spring 테스트코드/실무 적용] - Spring test code - service 테스트에서 만난 오류
반응형
'Spring > 테스트 코드' 카테고리의 다른 글
[스프링, 스프링 부트] Spring test - when()에서 발생한 에러 (0) | 2023.08.22 |
---|---|
[스프링, 스프링부트] Spring test - 스프링 시큐리티의 authentication객체를 어떻게 사용해야 할까? (0) | 2023.08.22 |
[스프링, 스프링 부트] Spring test - service 테스트에서 만난 오류 (0) | 2023.08.16 |
[스프링, 스프링 부트] Spring test - Mock에 대한 이해 (0) | 2023.08.09 |
[스프링, 스프링부트] Spring test - 테스트 코드의 기초(5) [CRUD 테스트] (0) | 2023.08.09 |