首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >等价于doReturn(x).when(y)...在mockk?

等价于doReturn(x).when(y)...在mockk?
EN

Stack Overflow用户
提问于 2019-04-15 12:31:55
回答 1查看 2.8K关注 0票数 3

我正在寻找doReturn(...).when(...).*的模拟等价物

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

我在mockK中找不到类似的东西。似乎每个{}总是在回答或返回之前运行代码块。

代码语言:javascript
复制
    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()
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-04-15 14:49:13

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

代码语言:javascript
复制
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.
        }
    }
}

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

代码语言:javascript
复制
every { other.fetchCar(listener) } returns listener.showCarSuccessful()

非常奇怪。首先,它不是在做你认为它正在做的事情--当你设置这个行为时,它会进行那个调用,你是在告诉你的mock返回调用的结果,而不是做那个调用。要做你想做的事情,你应该这样做:

代码语言:javascript
复制
every { other.fetchCar(listener) } answers {listener.showCarSuccessful()}

但即便如此,这行代码还是在你调用了被测试的类之后设置了模拟行为--首先设置模拟行为。

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

下面是让您的示例工作的尝试:

代码语言:javascript
复制
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时它会执行预期的操作

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55682624

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档