Как проверить макет интерфейса в тестовом методе с использованием библиотеки 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,

Рекомендации:

  1. Мокито Джавадок
  2. mockito-kotlin Вики документация
Другие вопросы по тегам