Как вы Mockk функции верхнего уровня Kotlin?
Mockk позволяет высмеивать статические функции, но как можно высмеивать функцию верхнего уровня Kotlin?
Например, если у меня есть файл Kotlin с именем HelloWorld.kt
как мне издеваться sayHello()
функционировать?
HelloWorld.kt
fun sayHello() = "Hello Kotlin!"
7 ответов
Есть способ макетировать функцию верхнего уровня:
mockkStatic("pkg.FileKt")
every { fun() } returns 5
Вам просто нужно знать, какой файл эта функция идет. Проверьте в JAR или трассировку стека.
Мне подошел следующий синтаксис.
mockkStatic(::sayHello.javaMethod!!.declaringClass.kotlin)
Я удивлен, что на
jvm-stdlib
пока для этого.
Чтобы добавить предыдущие ответы, это работает:
mockkStatic("pkg.FileKt")
every { fun() } returns 5
Где mockStatic принимает в качестве аргумента "package_name:class_file_name" Но для упрощения вызова mockStatick вы можете дать своему файлу имя для компилятора с помощью @file:JvmName прямо в файле.
HelloWorld.kt
@file:JvmName("hello")
fun sayHello() = "Hello Kotlin!"
HelloWorldTest.kt
mockkStatic("pkg.hello")
every { fun() } returns 5
Более подробное объяснение того, почему это необходимо, и другие примеры здесь:https://blog.kotlin-academy.com/mocking-is-not-rocket-science-mockk-advanced-features-42277e5983b5
Этот код не работает для меня с mockk версии 1.10.0, но хорошо работает в 1.11.0 (конечно, нужно изменить mockkStatic(::bar))
Utils.kt
@file:JvmName("UtilsKt")
package com.example.myapplication
fun foo(): Boolean {
return bar()
}
fun bar():Boolean {
return false
}
Контрольная работа
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [Build.VERSION_CODES.O_MR1])
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
mockkStatic("com.example.myapplication.UtilsKt")
every { bar() } returns true
assertTrue(foo())
}
}
@oleksiyp ответ работает. Вот пример:
HelloWorld.kt
package hello
fun sayHello() = "Hello Kotlin!"
Tests.kt
package hello
import io.mockk.every
import io.mockk.mockkStatic
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
class Tests {
@Test
fun `Top level mocking`() {
mockkStatic("hello.HelloWorldKt")
every { sayHello() } returns "Hello Mockk"
val actual = sayHello()
Assertions.assertEquals(actual, "Hello Mockk")
}
}
К сожалению, кажется, что мой оригинальный вопрос был слишком прост, потому что это не решает мою реальную проблему мира
Опираясь на ответ Сергея:
Вы могли бы иметь фактическую реализацию sayHello()
функция в переменной, то это значение по умолчанию параметра функции для sayHello()
,
Этот пример работает:
package tests
import io.mockk.every
import io.mockk.mockk
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
val sayHelloKotlin = { "Hello Kotlin!" }
fun sayHello(producer: () -> String = sayHelloKotlin): String = producer()
class Tests {
interface Producer {
fun produce(): String
}
@Test
fun `Top level mocking`() {
val mock = mockk<Producer>()
every { mock.produce() } returns "Hello Mockk"
val actual = sayHello(mock::produce)
Assertions.assertEquals(actual, "Hello Mockk")
}
}
Проблема в том, что вы изменяете производственный код, чтобы обслуживать тестирование, и это кажется надуманным.
Способ Гмаззо:
mockkStatic(::sayHello.javaMethod!!.declaringClass.kotlin)
работал у меня хорошо.
Только не забудьте:
unmockkStatic(::sayHello.javaMethod!!.declaringClass.kotlin)
в конце