Чи можна використовувати Mockito у Котліні?


82

Проблема, з якою я стикаюся, - це Matchers.anyObject()повернення null. При використанні для знущання над методом, який приймає лише ненульовані типи, він викликає виняток "Не повинно бути нулем".

`when`(mockedBackend.login(anyObject())).thenAnswer { invocationOnMock -> someResponse }

Знущаний метод:

public open fun login(userCredentials: UserCredentials): Response

2
На сайті спільноти kotlin йде дискусія про те, як уникнути цієї проблеми, перевірте її: devnet.jetbrains.com/thread/443551
SimY4

1
Дякую. Здається, devnet.jetbrains.com не дуже добре індексується Google.
atok

Відповіді:


76

Є два можливі способи вирішення:

private fun <T> anyObject(): T {
    Mockito.anyObject<T>()
    return uninitialized()
}

private fun <T> uninitialized(): T = null as T

@Test
fun myTest() {
    `when`(mockedBackend).login(anyObject())).thenAnswer { ... }
}

Іншим обхідним шляхом є

private fun <T> anyObject(): T {
    return Mockito.anyObject<T>()
}

@Test
fun myTest() {
    `when`(mockedBackend).login(anyObject())).thenAnswer { ... }
}

Ось ще кілька обговорень на цю тему, де спочатку пропонується обхідний шлях.


6
Я вважаю, що SO люб’язно просить вас також скопіювати вміст посилання у своїй відповіді, так що якщо посилання колись загине, ця відповідь все ще буде корисною.
Грег Копфф,

1
До жаль, в 1.0.0-бета-4584 цей спосіб не здається , працювати більше: kotlin.TypeCastException: null cannot be cast to non-null type X.
nhaarman

@nhaarman для мене ідеально працює, чи не могли б ви вказати мені конкретний випадок?
Сергій Машков

3
його не працює на Kotlin 1.2.40. хіба немає іншого обхідного шляху?
Амір Зіараті,

@nhaarman Kotlin 1.3.11, Mockito 2.7.12, Kotlin Mockito 1.5.0, січень 2019: Обхід 1 ... ну, це працює. Мій варіант використання знаходиться в межах даного / коли застереження.
milosmns

42

Для тих, хто потребує набору тексту any(type: Class<T>)

    private fun <T> any(type: Class<T>): T = Mockito.any<T>(type)

Це спрацювало б, і перевірка типу теж трапляється!


6
Можна уникнути передачі ClassName :: class.java в аргументі, використовуючи реіфіковані аргументи:inline fun <reified T> anyNonNull(): T = Mockito.any<T>(T::class.java)
Thales Pupo Araujo

28

Ви можете використовувати наступні допоміжні функції для використання збігів Mockito any (), eq () і capture () у Kotlin:

/**
 * Returns Mockito.eq() as nullable type to avoid java.lang.IllegalStateException when
 * null is returned.
 *
 * Generic T is nullable because implicitly bounded by Any?.
 */
fun <T> eq(obj: T): T = Mockito.eq<T>(obj)

/**
 * Returns Mockito.any() as nullable type to avoid java.lang.IllegalStateException when
 * null is returned.
 */
fun <T> any(): T = Mockito.any<T>()

/**
 * Returns ArgumentCaptor.capture() as nullable type to avoid java.lang.IllegalStateException
 * when null is returned.
 */
fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()

Див. MockitoKotlinHelpers.kt із сховища Android Architecture Blueprints від Google.


2
Дивиться , як URL переміщається: github.com/googlesamples/android-architecture/blob / ...
Surekha

Щиро дякую! Працює з останньою версією Mockito (v3.3.3) та Kotlin (v1.3.72)
Fatmajk

10

Я verifyбагато використовую, щоб переконатися, що параметри, передані функції, також правильні.

Для цього, і все ж уникаючи NPE, ви можете використовувати оператор kotlin's elvis. наприклад: verify(mock).func(same(my_obj) ?: my_obj)

Таким чином, mockito задовольняється, оскільки він фактично перевіряє змінну, а kotlin - тому, що ми передаємо ненульовий об'єкт.

Ще одна річ, на яку я натрапив, - це бібліотека mockito-kotlin, яка вирішує саме цю проблему https://github.com/nhaarman/mockito-kotlin


2

йому просто потрібно повернути ненульовий результат, коли ви використовуєте Mockito.any();

Mockito.any() ?: 0
Mockito.any() ?: HashMap<Int,Int>()
Mockito.any() ?: {}

...


0

Щоб продовжити відповідь, надану @makovkastar, ви можете надати збіжник, що підлягає онулюванню або неприпустимому, як це:

/**
 * Matcher that returns null
 */
private inline fun <reified T> any(): T = Mockito.any<T>()

/**
 * Matcher never returns null
 */
private inline fun <reified T> any(type: Class<T>): T = Mockito.any(type)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.