Kotlin에서 Mockito ArgumentCaptor 사용시 java.lang.NullPointerException: argumentCaptor.capture() must not be null 나오는 현상 해결 방법

2022. 12. 22. 22:31·Unit Testing
반응형

문제 상황

Kotlin에서 Mockito ArgumentCaptor을 사용하기 위해서 Java에서 쓰던 방법과 같은 방법을 사용하면 문제가 생긴다.

@Test
fun testLoginSuccessMockArgumentCaptor() {
    val repositorySuccessResult = LoginRepositoryResult.Success("test_token")
    Mockito.`when`(loginRepository.login(userName = "test", password = "test"))
        .thenReturn(repositorySuccessResult)

    val result = loginUseCase.logIn(userName = "test", password = "test")

    val argumentCaptor: ArgumentCaptor<String> = ArgumentCaptor.forClass(String::class.java)
    Mockito.verify(loginRepository, times(1)).login(argumentCaptor.capture(), argumentCaptor.capture())

    assertEquals(argumentCaptor.allValues[0], "test")
    assertEquals(argumentCaptor.allValues[1], "test")
    assertEquals(LoginUseCaseResult.Success("test_token"), result)
}

 

NullPointerException이 발생하는데 이유는 Java는 Nullable한 값을 사용하지만 Kotlin은 그렇지 않기 때문이다.

java.lang.NullPointerException: argumentCaptor.capture() must not be null
	at lecture4.LoginUseCaseTest.testLoginSuccessMockArgumentCaptor(LoginUseCaseTest.kt:50)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

 

 

첫번째 해결 방법

이 문제를 해결하려면 capture()시 non-Nullable 하게 만들어야 한다. 따라서 해결하기 위해서는 코드에 non-Nullable하게 값을 가져오는 함수를 추가하면 된다. 아래 capture() 함수를 코드에 추가하자.

fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()

 

이후 코드를 아래와 같이 바꿔야 한다. 위 capture가 argumentCaptor을 감싸도록 한다.

@Test
fun testLoginSuccessMockArgumentCaptor() {
    ...
    Mockito.verify(loginRepository, times(1)).login(capture(argumentCaptor), capture(argumentCaptor))
    ...
}

 

 

이제 테스트를 돌려보자. 테스트가 정상 통과됨을 볼 수 있다.

 

 

하지만 위 해결 방법은 공식적으로 제공하는 방법이 아니다. 따라서 웬만하면 아래의 해결 방법을 쓰도록 하자.

 

 

두번째 해결 방법

Mockito에서 공식적 API로 위 문제를 해결하는 방법을 제공한다.

 

이를 사용하기 위해서는 Mockito의 dependency를 바꿔야 한다. Mockito library를 mockito-kotlin을 사용하도록 변경한다. 기존 Mockito 라이브러리(mockito-inline 등)는 지운다.

testImplementation 'org.mockito.kotlin:mockito-kotlin:4.1.0'

 

이후 다음과 같이 argumentCaptor<String>()을 사용해 ArgumentCaptor을 생성한 후, 기존대로 argumentCaptor.capture()을 사용하면 문제가 해결된다.

@Test
fun testLoginSuccessMockArgumentCaptor() {
    ...
    val argumentCaptor = argumentCaptor<String>()
    Mockito.verify(loginRepository, times(1)).login(argumentCaptor.capture(), argumentCaptor.capture())

    assertEquals(argumentCaptor.allValues[0], "test")
    assertEquals(argumentCaptor.allValues[1], "test")
    ...
}

 

실행해보면 결과가 정상적으로 출력되는 것을 확인할 수 있다.

 

 

반응형

'Unit Testing' 카테고리의 다른 글

코드 작성 시 정적 변수와 정적 메서드 사용을 지양해야 하는 이유 알아보기  (0) 2022.12.24
MockitoJUnitRunner 사용해 Mockito 코드 깔끔하게 만들기 : @Mock  (0) 2022.12.23
[Mockito] ArgumentCaptor 사용해 객체의 interaction 기록하기  (0) 2022.12.21
[Mockito] when 사용법 한 번에 정리하기 : thenReturn, thenAnswer, doThrow  (0) 2022.12.20
[Unit Testing] Mockito 사용해 Test Double 만들기  (0) 2022.12.19


'Unit Testing' 카테고리의 다른 글
  • 코드 작성 시 정적 변수와 정적 메서드 사용을 지양해야 하는 이유 알아보기
  • MockitoJUnitRunner 사용해 Mockito 코드 깔끔하게 만들기 : @Mock
  • [Mockito] ArgumentCaptor 사용해 객체의 interaction 기록하기
  • [Mockito] when 사용법 한 번에 정리하기 : thenReturn, thenAnswer, doThrow
심플코드
심플코드
프로그래밍을 어렵지 않게 풀어서 설명하는 기술 블로그
    반응형
  • 심플코드
    심플코드
    심플코드
  • 전체
    오늘
    어제
    • 분류 전체보기 (96)
      • 안드로이드를 위한 Coroutines (2)
      • Unit Testing (19)
      • GitHub Actions (0)
      • 공식 문서 번역 (35)
        • Coroutines 공식 문서 (35)
      • 알고리즘 (7)
        • Kotlin 자료구조 (0)
        • 알고리즘 (7)
        • Kotlin으로 구현하는 자료구조 (0)
      • 코딩 테스트 (0)
      • Deep Learning (0)
      • Machine Learning Math (17)
        • Linear Algebra (17)
      • ML (0)
      • Docker (15)
      • Kubernetes (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

    • 코틀린 코루틴의 정석 책 출간 소식
  • 인기 글

  • 태그

    컨테이너
    코루틴 채널
    Coroutines Flow
    TensorFlow
    Coroutines Context
    Kotlin
    junit
    코루틴
    unit testing
    mockito
    Docker
    도커
    numpy
    Coroutines Channel
    Coroutines
    coroutine
    코루틴 Flow
    unit test
    Machine Learning
    pytorch
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
심플코드
Kotlin에서 Mockito ArgumentCaptor 사용시 java.lang.NullPointerException: argumentCaptor.capture() must not be null 나오는 현상 해결 방법
상단으로

티스토리툴바