Mockito-Kotlin 알아보기
Mockito-Kotlin 알아보기
Mockito는 유닛 테스트를 위한 Java mocking framework입니다.
Mockito를 사용하여 쉽게 Mock Object를 만들어 관리할 수 있습니다.
Mockito는 현재 Kotlin과 함께 작동하지만 구문이 최적이 아닙니다.
Kotlin에서는 모든 클래스가 기본적으로 final로 선언되어있어
Mockito는 기본적으로 mocking을 할 수 없는 등의 여러 문제가 있습니다.
그래서 Niek Haarman이 유지 관리하는 mockito-kotlin 라이브러리를 사용하도록 하겠습니다.
(글 쓴 시점으로는 Mockito lib는 kotlin을 공식 지원하지는 않지만 추후 제공 계획이 있다고 합니다.)
Mockito-Kotlin 기본 사용법
dependency implements
Mockito-Kotlin은 Maven Central 및 JCenter에서 사용할 수 있습니다.
gradle.project에 `jcenter()`를
그리고 gradle.app에 아래와 같이 추가합니다.
dependencies{
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0" //Mockito-Kotlin
testImplementation 'org.mockito:mockito-inline:2.21.0'
//Kotlin의 클래스는 기본이 final입니다. mocktio-inline을 추가해주거나 클래스를 open으로 선언해야 합니다.
}
mock 객체 만들기
mockito kotlin에서는 mock을 생성할 때 더 이상 클래스를 파라미터로 전달할 필요가 없습니다.
클래스의 유형을 유추할 수 있다면 아래와 같이 작성합니다.
val mock : MyClass = mock()
유형을 직접 추론할 수 없다면 아래와 같이 사용합니다.
val mock = mock<MyClass>()
stubbing
먼저 stub이란 테스트에서 호출된 요청에 대해 미리 준비해둔 결과를 제공합니다.
https://beomseok95.tistory.com/294
mockito kotlin은 when을 쓰지 않고 whenever를 사용합니다.
whenever(mock.stringValue()).thenReturn("test")
위의 식처럼 stubbing을 하거나 혹은 람다식을 사용할 수도 있습니다.
람다 식은 형이고 KStubbing<T> () -> Unit, T는 Mock의 타입입니다.
KStubbing <T>는 메서드 on을 제공하고 , (T)->R을 호출하여 mock을 생성하여 Stubbing 할 수 있습니다.
val mock = mock<MyClass> {
on {stringValue()}.doReturn ("test")
}
doRetun은 중위 연산자로도 정의되어 있기 때문에 아래와 같이도 사용 가능합니다.
val mock = mock<MyClass> {
on{stringValue()} doReturn "test"
}
verify
verify는 기존 mockito와 거의 동일합니다.
verify(myClass).doSomething("test")
Properties
mock으로 생성한 객체의 Property를 확인할 수도 있습니다. 아래와 같습니다.
interface Foo {
var bar : String
}
@Test
fun test() {
val foo = mock<Foo>()
foo.bar = "test"
verify(foo).bar = "test"
}
Argument Matchers
고차 함수를 사용하여 Argument Matcher의 명확한 기대치를 작성할 수 있습니다.
verify(myClass).setItems(argThat { size == 2 })
보다 자연스러운 읽기를 원한다면 아래와 같이도 사용 가능합니다.
verify(myClass).setItems(argForWhich { size == 2 } )
argThat과 argForWhich는 둘 다 (T)-> Boolean입니다. T는 매개변수의 타입입니다.
받은 인수에 대하여 더 많은 assertion은 수행하고자 한다면
check를 사용하여 아래와 같이 사용할 수 있습니다.
verify(myClass).setItems(check {
assertThat(it.size, is(2))
assertThat(it[0], is("test"))
})
check함수는 (T) -> Unit입니다.
Argument Captors
Argument Captors를 사용하면 Mockito에서와 같이
캡처한 인수에 대하여 assertion을 수행할 수 있습니다.
argumentCaptor<String>().apply {
verify(myClass, times(2)).setItems(capture())
assertEquals(2, allValues.size)
assertEquals("test", firstValue)
}
InOrder
Mockito-Kotlin에서는 inOrder 람다를 사용하여
순서를 검증할 수 있습니다
val a = ...
val b = ...
inOrder(a,b) {
verify(a).doSomething()
verify(b).doSomething()
}
Mockito-Kotlin 작성 예
@Test
fun doAction_doesSomething(){
/* Given */
val mock = mock<MyClass> {
on { getText() } doReturn "text"
}
val classUnderTest = ClassUnderTest(mock)
/* When */
classUnderTest.doAction()
/* Then */
verify(mock).doSomething(any())
}