mockito 如何判断一个函数是否调用其父函数?

bkkx9g8r  于 2022-11-08  发布在  其他
关注(0)|答案(1)|浏览(145)

我正在尝试为RecyclerView适配器编写一个单元测试。问题在于我使用了DiffUtil并返回有效负载diffs,它调用onBindViewHolder(holder: ViewHolder, position: Int, payloads: List<Any>而不是(嗯,除了)普通的onBindViewHolder(holder: ViewHolder, position: Int)。基于this tutorial的主要部分是:

override fun onBindViewHolder(holder: TravelinoNormalItemViewHolder, position: Int, payloads: MutableList<Any>) {
    if (payloads.isEmpty())
        super.onBindViewHolder(holder, position, payloads)
    else {
        if (payloads.any { it is InfoMessageChanged })
            holder.view.alarmMessage.text = this.items[position].infoMessage
    }
}

因此,我想为这个函数编写一个测试,但不知道如何验证或Assert所发生的事情。我创建了一个最小的可重复项目来演示我的问题。我不知道如何让两个测试都通过。

import io.mockk.MockKVerificationScope
import io.mockk.spyk
import io.mockk.verify
import org.junit.Before
import org.junit.Test

class TestyTest {

    private lateinit var child: ChildClass
    private lateinit var  verifyBlock: MockKVerificationScope.() -> Unit

    @Before
    fun setup() {
        // I've obviously tried many variations of mocks, spys, verifications, etc.
        val actual = ChildClass()
        child = spyk(actual)
        verifyBlock = {
            (child as ParentClass).doSomething("hi", any())
        }
    }

    @Test
    fun callParent() {
        child.doSomething("hi", true)
        verify(verifyBlock = verifyBlock)
    }

    @Test
    fun doNotCallParent() {
        child.doSomething("hi", false)
        verify(verifyBlock = verifyBlock, exactly = 0)
    }
}

// ParentClass is not mine to change.  Really is RecyclerView.Adapter
abstract class ParentClass {

    //public abstract void onBindViewHolder(@NonNull VH holder, int position);
    abstract fun doSomething(any: Any)

    //public void onBindViewHolder(@NonNull VH holder, int position, @NonNull List<Object> payloads)
    open fun doSomething(any: Any, callParent: Boolean) {
        println("ParentClass.doSomething(Any,Boolean)")
        doSomething(any)
    }
}

// My adapter
class ChildClass : ParentClass() {

    //public abstract void onBindViewHolder(@NonNull VH holder, int position);
    override fun doSomething(any: Any) {
        println("ChildClass.doSomething(Any)")
        println(any)
    }

    //public void onBindViewHolder(@NonNull VH holder, int position, @NonNull List<Object> payloads)
    override fun doSomething(any: Any, callParent: Boolean) {
        println("ChildClass.doSomething(Any,Boolean)")
        if(callParent) super.doSomething(any, callParent)
        else doSomething(any)
    }
}

verifyBlock被提取出来,以确保两个测试做同样的事情。我想验证当callParent=true调用父对象时,它调用父对象,而当callParent=false不调用父对象时,它不调用父对象。很简单,对吧?但是我想不出来。

kknvjkwl

kknvjkwl1#

找到了一个解决方案。我在子类中添加了一个shim,它不做任何有价值的事情,但创建了一个接缝来验证。

class ChildClass : ParentClass() {

    override fun doSomething(any: Any) {
        println("ChildClass.doSomething(Any)")
        println(any)
    }

    // added this
    fun doSomethingElse(any: Any) {
        doSomething(any)
    }

    override fun doSomething(any: Any, callParent: Boolean) {
        println("ChildClass.doSomething(Any,Boolean)")
        if(callParent) super.doSomething(any, callParent)
        else doSomethingElse(any)
    }
}

测试只是验证是否调用了新函数:

class TestyTest {

    private lateinit var child: ChildClass
    private val verifyBlock: MockKVerificationScope.() -> Unit = { child.doSomethingElse(any<String>()) }

    @Before
    fun setup() {
        val actual = ChildClass()
        child = spyk(actual)
    }

    @Test
    fun callParent() {
        child.doSomething("hi", true)
        verify(exactly = 0, verifyBlock = verifyBlock)
    }

    @Test
    fun doNotCallParent() {
        child.doSomething("hi", false)
        verify(exactly = 1, verifyBlock = verifyBlock)
    }
}

我不喜欢添加一个什么都不做的新函数(我可以看到有人--可能是我--试图在未来删除它,因为它什么都不做),但它现在解决了这个问题。

相关问题