티스토리 뷰
Spring
[Spring] java.lang.NullPointerException: save(...) must not be null
heemang.dev 2024. 7. 17. 23:051. Mock 테스트를 위한 라이브러리 추가
Mock 테스트를 위하여 gralde에 아래를 추가하였다.
// Mockito
testImplementation("org.mockito.kotlin:mockito-kotlin:4.0.0")
testImplementation("org.mockito:mockito-core:4.0.0")
testImplementation("org.junit.jupiter:junit-jupiter:5.8.2")
2. 서비스 레이어 작성
게시물을 작성하는 코드를 작성한다.
@Service
@RequiredArgsConstructor
class DiaryService(
private val diaryRepository: DiaryRepository
) {
@Transactional
fun createDiary(
user: User,
request: CreateDiaryRequestDto
): CreateDiaryResponseDto {
val diary = Diary.from(user, FeelStatus.valueOf(request.feel), request.content)
val result = diaryRepository.save(diary)
return CreateDiaryResponseDto(result.id!!, result.content, result.feelStatus)
}
}
3. Mock 테스트
@ExtendWith(MockitoExtension::class)
class DiaryServiceTest {
@Mock
lateinit var diaryRepository: DiaryRepository
@InjectMocks
lateinit var diaryService: DiaryService
@Test
@DisplayName("사용자는 일기를 작성할 수 있다.")
fun createDiaryTest() {
// given
val user = createUser()
val diary = createDiary(user)
val savedDiary = Diary(
feelStatus = diary.feelStatus,
user = user,
content = diary.content
)
ReflectionTestUtils.setField(savedDiary, "id", 1L)
val requestDto = CreateDiaryRequestDto(
feel = diary.feelStatus.toString(),
content = diary.content
)
whenever(diaryRepository.save(any())).thenReturn(savedDiary)
// when
val result = diaryService.createDiary(user, requestDto)
// then
assertThat(result).isNotNull
assertThat(result.diaryId).isEqualTo(savedDiary.id)
assertThat(result.content).isEqualTo(savedDiary.content)
assertThat(result.feel).isEqualTo(savedDiary.feelStatus)
}
}
JPA Repository의 save()를 스터빙하였으나 그림 1과 같은 오류가 발생한다.
4. 오류 발생 원인
결론적으로 오류가 발생한 이유는 스터빙할 때 any()를 사용하는 과정에서 패키지에 문제가 있었기 때문이다.
- org.mockito.kotlin.any : null을 허용하지 않는다.
- org.mockito.ArgumentMatchers.any : null을 허용한다.
org.mockito.ArgumentMatchers.any
org.mockito.kotlin.any
org.mockito.kotlin.any 패키지를 사용하여 스터빙을 한다면 save()에 null을 허용하지 않게 된다. 그러나 실제 테스트 코드에서 null을 매개변수 인자로 사용하게 되면 스터빙 설정을 찾지 못하게 된다. 따라서 다음 오류가 발생하는 것이다.
java.lang.NullPointerException: save(...) must not be null
import org.mockito.kotlin.any
whenever(diaryRepository.save(any())).thenReturn(savedDiary)
그렇다면 diary 객체를 스터빙에 사용하면 어떻게 될까? 테스트 코드에서 사용한 diary 객체와 서비스 레이어에서 생성한 diary 객체가 서로 다른 객체이므로 객체가 일치하지 않는 오류가 발생한다.
import org.mockito.kotlin.any
whenever(diaryRepository.save(diary)).thenReturn(savedDiary)
5. 오류 해결
결국 스터빙에서 null을 허용하는 org.mockito.ArgumentMatchers.any 패키지를 사용해야 한다.
import org.mockito.ArgumentMatchers.any
whenever(diaryRepository.save(any())).thenReturn(savedDiary)