Как проверить макет интерфейса в тестовом методе с использованием библиотеки KotlinTest?
У меня есть интерфейс, который связывается с моим докладчиком, который проверяет, являются ли поля формы действительными.
Мой интерфейс:
interface MainView {
fun showMessage(data: LoginEntity)
fun showEmailError()
fun showPasswordError()
}
Мой метод в презентере такой:
fun sendForm(loginData: LoginDataPresentation, view: MainView) {
if (isValid()) {
view.showMessage(mapData(loginData))
} else if (isValidPassword()) {
view.showPasswordError()
} else {
view.showEmailError()
}
}
Мой тестовый класс с KotlinTest:
class LoginPresentationKtTest : StringSpec() {
init {
"given a bunch of Login Data should be matched successfully" {
forAll(EmailGenerator(), PasswordGenerator(), { email: String, password: String ->
val loginData: LoginDataPresentation(email, password)
val mockMainView = mockMainView()
sendForm(loginData, mockMainView())
})
}
}
private fun mockMainView(): MainView {
//How to mock?????
}
}
Используя библиотеку KotlinTest, есть ли способ проверить, что вызов метода showMessage класса MainView выполнен при условии, что сгенерированный адрес электронной почты и пароль всегда верны? Можно ли использовать фиктивную библиотеку типа mockito?
С ответом пользователя @mkobit, следующая модификация может быть сделана с использованием Mockito-Kotlin, с которой тест будет выглядеть следующим образом:
class LoginPresentationKtTest : StringSpec() {
init {
"given a bunch of Login Data should be matched successfully" {
forAll(EmailGenerator(), PasswordGenerator(), { email: String, password: String ->
val loginData = LoginDataPresentation(email, password)
val mockMainView = Mockito.mock(MainView::class.java)
sendForm(loginData, mockMainView)
verify(mockMainView).showMessage()
true
})
}
}
}
При каждом выполнении цикла будет проверяться, была ли вызвана функция verify (). Если поток выполнения является ожидаемым, он перейдет к следующему выполнению цикла. В случае сбоя функции verify () в консоли произойдет ошибка, указывающая, что тест не пройден.
Есть ли лучшее решение?
1 ответ
Вы упомянули Mockito, поэтому я покажу вам пример. Я собираюсь также использовать nhaarman/mockito-kotlin
библиотека, которая делает его более выразительным и простым в использовании в Kotlin.
import com.nhaarman.mockito_kotlin.mock
val mockMainView: MainView = mock()
Это в основном эквивалентно val mockMainView = Mockito.mock(MainView::class.java)
из Мокито. В Kotlin мы можем получить более сжатый и компактный код благодаря некоторым его функциям.
Если вы хотите выполнить некоторую заглушку (например, возвращаемые значения, исключения и т. Д.), Вы можете использовать whenever
(Mockito.when(T methodCall)
) API. Смотрите документацию для деталей. Я собираюсь пропустить это сейчас.
Итак, теперь вы бы вызвать метод:
sendForm(loginData, mockMainView)
Затем вы можете выполнить проверку. С помощью mockito-kotlin
метод verify
(Mockito.verify(T mock)
) поведение.
import com.nhaarman.mockito_kotlin.verify
verify(mockMainView).showPasswordError()
verify(mockMainView).showEmailError()
С помощью any()
(Mockito.any(Class<T> type)
), чтобы не просто проверить, что метод вызывается с любым значением.
import com.nhaarman.mockito_kotlin.any
verify(mockMainView).showMessage(any())
Существует поддержка других сопоставителей аргументов, если вы хотите быть более точным с тем, что передается.
Обратите внимание, что Mockito также поддерживает opt-in mocking финальных классов / методов. Пример для Gradle будет что-то вроде добавления файла в src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
с содержанием mock-maker-inline
,
Рекомендации:
- Мокито Джавадок
mockito-kotlin
Вики документация