#kotlin #mocking #mockito
#kotlin #издевательство #mockito
Вопрос:
Сегодня я наткнулся на ситуацию, которую я не понимаю, возможно, из-за отсутствия понимания того, как mockito и mockito-kotlin работают внутри.
Учитывая приведенный ниже код, с моей точки зрения новичка в Kotlin, у меня есть два довольно похожих интерфейсных метода. Один возвращает логическое значение, одну строку. В моем примере обе функции приостановлены, как и в моей реальной ситуации, мои функции тоже.
class ITestInterface {
suspend fun returnBoolean(): Boolean {
return true
}
suspend fun returnSomeString() : String {
return "String"
}
}
@Test
fun demoTest() {
val implMock = mock<ITestInterface> {
on {
runBlocking {
returnSomeString()
}
} doReturn "Hello"
on {
runBlocking {
returnBoolean()
}
} doReturn false
}
}
По моим наблюдениям, когда я запускаю тест, подобный изображенному выше, я получаю следующее сообщение об ошибке
com.nhaarman.mockitokotlin2.MockitoKotlinException: NullPointerException thrown when stubbing.
This may be due to two reasons:
- The method you're trying to stub threw an NPE: look at the stack trace below;
- You're trying to stub a generic method: try `onGeneric` instead.
at com.nhaarman.mockitokotlin2.KStubbing.on(KStubbing.kt:72)
at com.rewedigital.fulfillment.picking.components.substitute.DemoTest.demoTest(DemoTest.kt:30)
[…]
Эксперименты показали, что
- поведение только отображается логической функцией возврата, а не returnSomeString()
- удаление ключевого слова suspend из функции returnBoolean устраняет ошибку
- использование onGeneric, как предложено в сообщении об ошибке, также устраняет ошибку
Кто-нибудь может объяснить, почему это происходит? В какой степени мы должны здесь использовать дженерики? И каков был бы правильный способ решения проблемы в нашем реальном приложении? Наличие множества on {} и некоторого onGeneric {} ?
Спасибо за вашу помощь!
Ответ №1:
Вы должны использовать метод onBlocking, чтобы правильно имитировать функцию приостановки
Пожалуйста, попробуйте следующий код:
@Test
fun demoTest() {
val implMock = mock<ITestInterface> {
onBlocking {
returnSomeString()
} doReturn "Hello"
onBlocking {
returnBoolean()
} doReturn false
}
runBlocking {
// Execute your code here
assertThat(implMock.returnSomeString()).isEqualTo("Hello")
assertThat(implMock.returnBoolean()).isEqualTo(false)
}
}