테스트 작성중 NativeWebRequest
인터페이스를 mocking 해야할 상황이 있었고
기존에 Junit5 + mockito 환경에서 테스트할때는 다음과 같이 mocking하곤 했다.
val mockNativeWebRequest: NativeWebRequest = Mockito.mock(NativeWebRequest::class.java)
테스트 대상은 실제로 웹 요청을 하는 테스트 등이 아니었고 ResponseEntity를 생성하기 위해 파라미터로
request를 받긴 했지만 그동안 stub을 명시적으로 하지 않아도 문제가 되지 않았다.
최근 들어 kotest + mockk로 테스트를 작성하기 시작했고, NativeWebRequest객체를 모킹할 일이 생겨
mockito와 동일하게 mock NativeWebRequest을 다음과 같이 작성했다.
val mockNativeWebRequest: NativeWebRequest = mockk()
테스트 도중 의도치 않게 mockNativeWebRequest에서 에러가 발생한다.
getHeaderValues("")
라는 메서드를 stubing하지 않고 호출했다는 에러가 발생했다.
application/problem+json (RFC 7807) 형식의 에러응답을 따르기 위해 Problem 라이브러리를 사용하는데, 에러 응답을 생성 로직중 Content Negotitation 과정에서 NativeWebRequest객체를 참조한다.
mockk를 통해 초기화 했을때 당연히 getHeaderValues가 명시적으로 stub되지 않았기 때문에 에러가 발생한것이 이해되나, 왜 mockito를 통해 초기화 하였을땐 에러가 발생하지 않았던 것일까?
val mockkNativeWebRequest: NativeWebRequest = mockk()
val mockitoNativeWebRequest: NativeWebRequest = Mockito.mock(NativeWebRequest::class.java)
각각 mockk, mockito를 이용해 초기화한 객체를 명시적으로 stub하지 않고
getHeader("")메서드를 호출해보면 다음과 같다
mockk는 stub 옵션은 모든 메서드 호출에 대해 명시적으로 stub
mockito는 default stub
mockito도 strict 설정이가능하나 default설정은 RETURNS_DEFAULT
로 stub하지 않은 메서드 호출은 기본값 ( 0, null, [] etc)등이 반환된다.
The default Answer of every mock if the mock was not stubbed. Typically it just returns some empty value.
Answer can be used to define the return values of unstubbed invocations. This implementation first tries the global configuration.
If there is no global configuration then it uses ReturnsEmptyValues (returns zeros, empty collections, nulls, etc.)
mockito 문서
반면 mockk는 strict가 기본 설정이어서 메서드 호출이 전부 되지 않았던 것
default mock is strict
mockk 문서
mockk도 옵션으로 relaxed-mock 설정으로 사용 가능하다.
mockk relxed-mock
val mockNativeWebRequest: NatibeWebRequest = mockk(relaxed = true)
위와 같이 구현했을때 mockito와 동일하게 getHeader
호출시 null이 반환
val mockNativeWebRequest: NativeWebRequest = ServletWebRequest(MockHttpServletRequest(), MockHttpServletResponse())
spring에서 제공하는 MockHttpServletRequest
, MockHttpServletResponse
클래스를 사용하는 방법이 있다.
실제로
웹 요청 응답에서도 사용할 수 있을만큼 도메인, 헤더값등이 전부 초기화 되어있어서 유용하게 쓰일수 있다.