0

我有一个客户端类(在 Android 应用程序中用 Kotlin 编写),它实现了一个接口ReadyCallback(在应用程序的库中用 Java 编写,应用程序依赖于这个库)。在客户端中,我有一个createClient()方法将创建一个带有 ReadyCallback 参数的客户端。如果它准备好了,我将通过调用来执行其他任务classC.otherMethod(),如果没有准备好,我只是创建客户端而不做其他事情:

在图书馆:

// Somewhere in this library, I have logic to call `readyCallback.onReady()` when I consider it's "ready"
interface ReadyCallback {
    void onReady()
}

class Manager {
    private final ReadyCallback readyCallback;
    public void onConnected(final boolean isConnected) {
        if (isConnected) {
            readyCallback.onReady();
        }
    }
}

在应用程序中:

class ClassA internal constructor(private val clientProvider: ClassB, private val classC: ClassC, private val classD: ClassD) : ReadyCallback {
    fun createClient() {
        val client = clientProvider.create(getReadyCallback())
    }

    private fun getReadyCallback() {
        return ReadyCallback { onReady() }
    }

    override fun onReady() {
        logInfo { "It's ready! Now do some stuff by calling classC.otherMethod()" }
        classC.otherMethod()
    }
}

在单元测试中,我想验证当我创建客户端并且它准备好时,classC 的 otherMethod() 将被调用。我尝试执行以下操作,但不正确:

import com.nhaarman.mockitokotlin2.*
import org.junit.*

class ClassATest {
    lateinit var unitUnderTest: ClassA
    lateinit var clientProviderMock: ClassB
    lateinit var classCMock: ClassC
    lateinit var clientMock: ClassD

    @Before
    override fun setup() {
        super.setup()
        clientProviderMock = mock()
        classCMock = mock()
        clientMock = mock()
        unitUnderTest = ClassA(clientProvider = clientProviderMock, classC = classCMock, classD = classDMock)

        whenever(clientProviderMock.create(any()).thenReturn(client)
    }

    @Test
    fun `when create client then call otherMethod`() {
        unitUnderTest.createClient()
        verify(classCMock).otherMethod()
    }
}

错误信息显示:

Wanted but not invoked:
classC.otherMethod();
Actually, there were zero interactions with this mock.

我认为我得到这个错误的原因是,如果我不调用getReadyCallback(),这意味着我没有调用回调,所以没有调用 classC.otherMethod()。但除此之外,我真的坚持这一点,我不知道如何对我的期望行为进行单元测试(如果准备好,将调用 classC.otherMethod(),如果未准备好,则不会调用此方法)。

我知道我不能做下面这样的事情,因为 unitUnderTest 不是一个模拟对象:

callbackMock = mock()
whenever(unitUnderTest.getReadyCallback()).thenReturn(callbackMock)
whenever(clientProviderMock.create(callbackMock).thenReturn(client)

谁能帮帮我?

4

2 回答 2

0

我能想到的唯一方法是在回调的onReady()方法中添加一个布尔标志。所以会变成:

在图书馆:

interface ReadyCallback {
    void onReady(final boolean isReady)
}

class Manager {
    private final ReadyCallback readyCallback;
    public void onConnected(final boolean isConnected) {
        if (isConnected) {
            readyCallback.onReady(true);
        } else {
            readyCallback.onReady(false);
        }
    }
}

在应用程序中:

class ClassA internal constructor(private val clientProvider: ClassB, private val classC: ClassC, private val classD: ClassD) : ReadyCallback {
    fun createClient() {
        val client = clientProvider.create(getReadyCallback())
    }

    private fun getReadyCallback() {
        return ReadyCallback { isReady -> onReady(isReady) }
    }

    override fun onReady(isReady: Boolean) {
        if (isReady) {
            logInfo { "It's ready! Now do some stuff by calling classC.otherMethod()" }
            classC.otherMethod()
        }
    }
}

在单元测试中:

import com.nhaarman.mockitokotlin2.*
import org.junit.*

class ClassATest {
    lateinit var unitUnderTest: ClassA
    lateinit var clientProviderMock: ClassB
    lateinit var classCMock: ClassC
    lateinit var clientMock: ClassD

    @Before
    override fun setup() {
        super.setup()
        clientProviderMock = mock()
        classCMock = mock()
        clientMock = mock()
        unitUnderTest = ClassA(clientProvider = clientProviderMock, classC = classCMock, classD = classDMock)

        whenever(clientProviderMock.create(any()).thenReturn(client)
    }

    @Test
    fun `when create client and ready then call otherMethod`() {
        unitUnderTest.onReady(true)
        unitUnderTest.createClient()
        verify(classCMock).otherMethod()
    }

    @Test
    fun `when create client and not ready then do not call otherMethod`() {
        unitUnderTest.onReady(false)
        unitUnderTest.createClient()
        verifyZeroInteractions(classCMock)
    }
}

但是我仍然不知道如何在没有回调方法中的布尔参数的情况下进行测试。有谁知道这是怎么做到的吗?

于 2021-09-13T17:48:52.170 回答
0

我想我想通了。我不需要 in 中的参数onReady()。在图书馆:

interface ReadyCallback {
    void onReady()
}

// place to determine when is "ready"
class Manager {
    private final ReadyCallback readyCallback;
    public void onConnected(final boolean isConnected) {
        if (isConnected) {
            readyCallback.onReady();
        }
    }
}

在应用程序中:

class ClassA internal constructor(private val clientProvider: ClassB, private val classC: ClassC, private val classD: ClassD) : ReadyCallback {
    fun createClient() {
        val client = clientProvider.create(getReadyCallback())
    }

    private fun getReadyCallback() {
        return ReadyCallback { onReady() }
    }

    override fun onReady() {
        logInfo { "It's ready! Now do some stuff by calling classC.otherMethod()" }
        classC.otherMethod()
    }
}

在单元测试中:

import com.nhaarman.mockitokotlin2.*
import org.junit.*

class ClassATest {
    lateinit var unitUnderTest: ClassA
    lateinit var clientProviderMock: ClassB
    lateinit var classCMock: ClassC
    lateinit var clientMock: ClassD

    @Before
    override fun setup() {
        super.setup()
        clientProviderMock = mock()
        classCMock = mock()
        clientMock = mock()
        unitUnderTest = ClassA(clientProvider = clientProviderMock, classC = classCMock, classD = classDMock)

        whenever(clientProviderMock.create(any()).thenReturn(client)
    }

    @Test
    fun `when create client and ready then call otherMethod`() {
        unitUnderTest.onReady()
        unitUnderTest.createClient()
        verify(classCMock).otherMethod()
    }

    @Test
    fun `when create client and not ready then do not call otherMethod`() {
        unitUnderTest.createClient()
        verifyZeroInteractions(classCMock)
    }
}
于 2021-09-15T02:15:53.170 回答