Можно ли использовать Mockito с Kotlin без открытия класса?

Как мы, наверное, знаем, по умолчанию класс Kotlin, определенный после его определения, является окончательным, если он явно не объявлен open.

Это вызовет вызов, когда мы захотим его использовать, используя Mockito. Нам нужно явно объявить его как open. Есть ли способ, которым мы могли бы избежать объявления его как open, в то время как он мог бы Mock его для нашего тестирования?

Ответ 1

Mockito2 теперь может также имитировать финальные классы.

Однако эта функция выбрать, поэтому вам нужно включить ее вручную.
Для этого вам необходимо определить файл /mockito-extensions/org.mockito.plugins.MockMaker, содержащий строку mock-maker-inline

См. например,
http://hadihariri.com/2016/10/04/Mocking-Kotlin-With-Mockito/ или  https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#unmockable
для быстрого введения

на боковой ноте, в настоящее время не работает для android

Ответ 2

Есть три способа узнать, как вы можете издеваться над классами Kotlin:

  • Используйте интерфейсы вместо классов. В этом случае вы заменяете все обычаи определенного класса соответствующим интерфейсом. И в тестировании кода вы обманываете интерфейс.

    interface Something { /* ... */ }
    
    class SomethingImpl : Something { /* ... */ }
    
    fun processSomething(something: Something) { /* ... */ }
    
    val something = mock(Something::class.java)
    processSomething(mock)
    
  • Сделать классы открытыми, что не очень удобно.

  • Используйте PowerMock вместо Mockito. Используя ClassLoader, вы можете сделать гораздо больше, чем с помощью Mockito.

Я предпочитаю первый подход, потому что неплохо работать с интерфейсами вместо классов, даже если вы не используете насмешливые фреймворки.

Ответ 3

Плагин MockMaker, похоже, не работает при запуске тестов эспрессо. Таким образом, вы можете использовать Kotlin all-open pugin.

Добавьте плагин в build.gradle:

buildscript {
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
    }
}

apply plugin: "kotlin-allopen"

Укажите аннотацию, которая сделает класс открытым:

allOpen {
    annotation("com.my.MyMockable")
}

Создайте свою аннотацию, которая может использоваться для аннотирования классов:

@Target(AnnotationTarget.CLASS)
annotation class MyMockable

Затем, чтобы сделать свой класс и его общедоступные методы Mockable (открытыми), аннотировать его аннотацией:

@MyMockable