kotlin - 相当于 doReturn(x).when(y)... 在 mockk 中?

标签 kotlin mocking mockito mockk

我正在寻找一个等效于 doReturn(...).when(...).*

我正在编写一些涉及大量系统类的单元测试(测试契约(Contract)),因此需要拦截我无法控制的方法并返回一些回调(代码中的方法最终会返回) )。在 mockito 中,我可以做类似 doReturn(...).when(...).*

我在 mockK 中找不到类似的东西。似乎 every{} 总是在回答或返回之前运行该 block 。

    class Vehicle: Listener {

    fun displayCar(listener:Listener){
        OtherClass().fetchCar(listener)
    }

    override fun showCarSuccessful() {
        //do something
    }
}

    class OtherClass {
    //assume its an outside function that returns nothing but invokes a method of listener call back
    fun fetchCar(listener: Listener) {
        //... Some system level operations that I don't have control to generate mock objects but in the test I want to use the listener to call some method so that I can
        // test some contracts
        listener.showCarSuccessful()
    }
}

    class Tests {
    @Test
    fun testCarSuccess() {
        val listener: Listener = mockk(relaxed = true)
        val vehicle = Vehicle()
    //also tried with mockkClass and others
        val other: OtherClass = mockk(relaxed = true)
   every { other.fetchCar(listener) } returns {listener.showCarSuccessful()}
   vehicle.displayCar(listener)
//do some verification checks here
    }
}

    interface Listener {
    fun showCarSuccessful()
}

最佳答案

every{} block 是您的 when 子句。您可以设置多个条件来返回不同的结果。请参阅设置固定 returns 和执行程序 answers

的示例
import io.mockk.MockKException
import io.mockk.every
import io.mockk.mockk
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test

class MyClass {

    fun add(operand1: Int, operand2: Int): Int {
        TODO()
    }
}

class MockkTest {

    @Test
    fun testMocking() {

        val myClassMock = mockk<MyClass> {
            every { add(1, 2) } returns 3 // Set behaviour
            every { add(2, 2) } returns 4 // Set behaviour
            every { add(3, 4)} answers {args[0] as Int * args[1] as Int} // Programmatic behaviour
        }

        Assertions.assertEquals(3, myClassMock.add(1, 2))
        Assertions.assertEquals(4, myClassMock.add(2, 2))
        Assertions.assertEquals(12, myClassMock.add(3, 4))

        Assertions.assertThrows(MockKException::class.java) {
            myClassMock.add(5, 6) // This behaviour has not been set up.
        }
    }
}

但是,特别是在您的示例中,我发现这一行:

every { other.fetchCar(listener) } returns listener.showCarSuccessful()

很奇怪。首先,它没有做你认为它正在做的事情——它会在你设置这个行为时进行那个调用,你告诉你的模拟返回那个调用的结果,而不是做那个 cal。做你想做的事,你应该这样做:

every { other.fetchCar(listener) } answers {listener.showCarSuccessful()}

但即便如此,这行代码也是在您调用待测类之后设置模拟行为 - 首先设置模拟行为。

此外,您在嵌套模拟中的顶级模拟中设置副作用很奇怪。当然,为了测试你的 Vehicle 类,你要做的就是验证它的内部类是用正确的参数调用的。另外,Vehicle 如何获得对 OtherClass 模拟的引用,它正在实例化一个新模拟并调用该函数。

这是使您的示例工作的尝试:

import io.mockk.mockk
import io.mockk.verify
import org.junit.jupiter.api.Test

interface Listener {
    fun showCarSuccessful()
}

class Vehicle(val other: OtherClass) : Listener {

    fun displayCar(listener: Listener) {
        other.fetchCar(listener)
    }

    override fun showCarSuccessful() {
        //do something
    }
}


class OtherClass {
    //assume its an outside function that returns nothing but invokes a method of listener call back
    fun fetchCar(listener: Listener) {

    }

}

class VehicleTest{

    @Test
    fun testDisplayCar(){
        val listener: Listener = mockk(relaxed = true)
        val other: OtherClass = mockk(relaxed = true) //also tried with mockkClass and others
        val vehicle = Vehicle(other)

        vehicle.displayCar(listener)

        verify{ other.fetchCar(listener) }
    }
}

即使这样,我认为可能仍然有点偏离 - 我怀疑您希望 Vehicle 传递给 OtherClass 的监听器是它本身,而不是参数...

您还应该为 OtherClass 编写一个单独的测试,以确保它在您调用 fetchCar

时符合您的预期

关于kotlin - 相当于 doReturn(x).when(y)... 在 mockk 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55682624/

相关文章:

android - RecyclerView 右滑添加图标

java - mockito-groovy-支持不工作

kotlin - 在 Intellij IDE 中编译 Kotlin 时无法删除缓存目录

android - Android Studio 无法识别 .kt 文件

python - 检查是否使用不同参数多次调用函数

java - 如何使用 Mockito 测试不模拟对象的异步方法?

unit-testing - PHPUnit 和接缝

spring - 在方法上具有 @Retryable 注释的模拟 Spring @Service 失败并出现 UnfinishedVerificationException

java - 无法从 Class<PowerMockRunner> 转换为 Class<?延伸运行者>

android - 这段代码this@MainActivity是什么意思?