티스토리 뷰

반응형

문제 상황


먼저 저의 상황은 코틀린(kotlin) 언어로 mockito를 사용하는 환경에서 발생하였습니다.
코틀린언어가 아닌 다른 언어를 사용하셨다면 저의 케이스와 다른 경우일 확률이 높습니다.

mockito의 Argument matchers의 eq() 메서드를 사용시에 문제가 발생하였다.

 

문제 상황을 가정하기 위해 먼저 Person 클래스를 하나 생성하자

class Person {
    fun isDeveloper(name: String, age: Int): Boolean {
        return true
    }
}

 

Argument matchers를 이용해 name이 "charlie"이고 age는 any()로 스텁(stub) 진행 하였다.

// NullPointerException 발생
`when`(mock.isDeveloper(eq("charlie"), anyInt())).thenReturn(false)

이러자 NullPointerException 에러가 발생하였다.

 

자세한 에러내용을 아래와 같다.

java.lang.NullPointerException: eq("charlie") must not be null

 

 

문제 해결


에러 내용을 보니 eq("charlie") 부분 때문에 문제가 일어난걸로 보이므로 eq() 메서드를 한번 살펴보자.

 

Argument Matchers의 eq메서드 코드

public static <T> T eq(T value) {
    reportMatcher(new Equals(value));
    if (value == null) return null;
    return (T) Primitives.defaultValue(value.getClass());
}

eq메서드의 코드를 보니 null을 다루는걸 볼 수 있다.

자바언어의 경우 기본적으로 null을 허용하지만 코틀린언어의 경우 기본적으로 null을 허용하지 않는데 이러한 차이때문에 NullPointerException 에러가 발생한것이다.

 

그러면 문제 해결은 간단하다. name 파라미터가 null을 허용하도록 변경해주면 된다.

class Person {
    // String -> String? 변경
    fun isDeveloper(name: String?, age: Int): Boolean {
        return true
    }
}

name파라미터 타입을 String? 타입으로 변경하니 에러가 해결되었다.

 

그러나 Person이라는 객체가 테스트 만을 위한 객체라면 괜찮지만 만약 실제로 사용하는 코드인데 테스트만을 위해 null을 허용해주도록 변경해주는것은 실제코드보다 테스트코드가 더 우선시되는것 같아 부적절하게 느껴진다.

 

테스트코드도 중요하지만 테스트코드는 결국 실제코드가 잘 작동하는지 검증하기를 위함이지 실제코드보다 우선순위가 높은것은 아니다.

 

 

mockito-kotlin 사용


그래서 실제 코드를 변경하지 않는 방법인 mockito-kotlin을 이용해 에러를 해결해보자.

(mockito-kotlin은 코틀린에서 mockito를 사용하는데 작은 helper 기능을 제공하는 라이브러리이다.)

 

mockito-kotlin 적용

build.gradle

testImplementation("org.mockito.kotlin:mockito-kotlin:4.1.0")

mockito-kotlin 라이브러리를 추가.

버전에 대한 정보는 여기를 참고하시면 됩니다.

 

문제 해결

mockito-kotlin의 Argument matcher를 사용

val mock = mock<Person>()
whenever(mock.isDeveloper(eq("charlie"), any())).thenReturn(false)
  • mockito-kotlin은 when대신 whenever을 사용한다.

mockito-kotlin을 적용하는 것만으로 기존에 발생하던 NullPointerException은 더이상 발생하지 않고 정상 동작을 하게 된다.

추가로 Person객체를 수정하지 않아도 되기때문에 더이상 실제 코드가 변경되는 일이 발생하지 않게 되었다.

 

그러면 왜 mockito-kotlin의 eq() 메서드는 문제가 없었을까??

fun <T> eq(value: T): T {
    return ArgumentMatchers.eq(value) ?: value
}

eq() 메서드 코드를 보면 내부적으로 null인 경우는 그냥 value를 리턴을 통해 널 문제를 해결해주는걸 볼 수 있다.

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함