Проверьте лямбда-функции в Android с Kotlin - PullRequest
0 голосов
/ 09 мая 2018

Мне нужно провести модульное тестирование функции doClassAction, и внутри нее вызывается функция doStoreAction для объекта store. doStoreAction принимает два параметра, одно целое и одну функцию, как в примере ниже

class MyStore() {

    fun doStoreAction(num: Int, callback: (text: String) -> Unit) {
        // It does something 
        // ...
        // and when it's done it calls the callback

        return callback("some text")
    }
}

class MyClass(private val store: MyStore,
              private val objectX: MyObject) {

    fun doClassAction(num: Int) {
        store.doStoreAction(num) { callbackResult ->
            // Action (potentially asynchronous)
            // that will happen after obtaining the value via the callback

            objectX.doObjectAction(callbackResult)
        }
    }
}

Я использую Mockito, и пока мой тест имеет следующие строки

@Test
fun doClassActionTest() {
    val mockStore = mock(MyStore::class.java)
    val mockObject = mock(MyObject::class.java)
    val class = MyClass(mockStore, mockObject)
    class.doClassAction(42)
}

Но он не компилируется, потому что при вызове метода не указывается обратный вызов ... Я не хочу перезаписывать его, поскольку хочу, чтобы тест использовал исходный и проверял, что все внутри вызывается правильно , как:

when(objectX.doObjectAction(anyString())).doNothing()
verify(objectX, times(1)).doObjectAction(callbackResult)

Есть ли способ вызвать метод, а также посмеяться над ответом обратного вызова на значение, которое я установил в тестах, но все же оно проходит исходный поток кода?

1 Ответ

0 голосов
/ 11 мая 2018

После нескольких дней испытаний и чтения об этом, я наконец нашел решение, которое работает, и я поделюсь им здесь для тех, кто окажется в одном и том же рассоле

@Test
fun doClassActionTest() {
    val mockStore = mock(MyStore::class.java)
    val mockObject = mock(MyObject::class.java)
    val myClass = MyClass(mockStore, mockObject)
    val input = 42
    val resultCallback = "test result"

    `when`(mockStore.doStoreAction(any(), any())).then { invocation ->
        (invocation.arguments[1] as (String) -> Unit).invoke(resultCallback)
    }

    myClass.doClassAction(input)

    verify(mockObject, only()).doObjectAction(resultCallback)
}

Предостережение: не забывайте помещать классы, над которыми вы издеваетесь, и методы, вызываемые этими классами, как open в Котлине, иначе может быть ложных срабатываний

P.s. Я также использовал несколько встроенных функций, извлеченных из библиотеки mockito-kotlin , таких как:

inline fun <reified T : Any> any() = Mockito.any(T::class.java) ?: createInstance<T>()

inline fun <reified T : Any> createInstance(): T = createInstance(T::class)

fun <T : Any> createInstance(kClass: KClass<T>): T = castNull()

@Suppress("UNCHECKED_CAST")
private fun <T> castNull(): T = null as T
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...