Android/Test

Mockito-Kotlin 알아보기

봄석 2019. 10. 28. 16:36

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

 

Test Stub이란 ?

Test Stub이란 ? stub에 대하여 알아보도록 하겠습니다 stub이란 ? stub이란 토막,꽁초,남은부분,몽당연필.. 이라는 뜻으로 dummy객체가 마치 실제로 동작하는 것 처럼 보이도록 만들어놓은 것입니다. https://en...

beomseok95.tistory.com

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())
}