如何模拟 Android `Tasks.await()`?

Bas*_*tor 3 android unit-testing task mockito kotlin

因此,我正在编写一个方法来对与 Firebase 身份验证的交互进行单元测试 - 我已成功模拟了所需的所有其他内容,但我不确定如何模拟被测方法中的调用Tasks.await(someTask).someValue

因为Tasks.await()是静态的,所以我不能真正嘲笑它。

我可以模拟任务本身,但不能模拟对await 方法的调用。有什么方法可以让我Tasks.await()认为该任务是真实的,以便它正常运行吗?

我在这里可以做些什么吗?

cut*_*iko 5

我的协程有这个问题await。我认为解决方案是模拟任务,因为协程await()基本上包装了侦听器。我所做的是模拟最简单的路径await

     /**
     * Mocks the simplest behaviour of a task so .await() can return task or throw exception
     * See more on [await] and inside of that on awaitImpl
     */
    private fun mockTask(exception: Exception? = null): Task<Void> {
        val task: Task<Void> = mockk(relaxed = true)
        every { task.isComplete } returns true
        every { task.exception } returns exception
        every { task.isCanceled } returns false
        val relaxedVoid: Void = mockk(relaxed = true)
        every { task.result } returns relaxedVoid
        return task
    }
Run Code Online (Sandbox Code Playgroud)

如果你想知道的话,我正在使用Mockk 。

这是解释。内部await简单地调用一个私有的awaitImpl

public suspend fun <T> Task<T>.await(): T = awaitImpl(null)
Run Code Online (Sandbox Code Playgroud)

然后awaitImpl这样做

    // fast path
    if (isComplete) {
        val e = exception
        return if (e == null) {
            if (isCanceled) {
                throw CancellationException("Task $this was cancelled normally.")
            } else {
                @Suppress("UNCHECKED_CAST")
                result as T
            }
        } else {
            throw e
        }
    }
    
    return suspendCancellableCoroutine { cont ->
        addOnCompleteListener {...

Run Code Online (Sandbox Code Playgroud)

注释在源代码中。因此,该路径在添加用于测试的侦听器之前负责解析。我们只需要控制输出即可。所以模拟是说“输入完整的条件,然后我们控制异常是否为空。如果异常不为空,它将抛出它,否则,我们确定未取消,因此返回 Void”。

这让我想到:您可以将Void, 更改为另一种类型。我正在为Task<Void>.

然后使用它。

//for success
every { yourGoogleDependency.thatReturnsTask() } returns mockTask()

//for failure
every { yourGoogleDependency.thatReturnsTask() } returns mockTask(Exception())
Run Code Online (Sandbox Code Playgroud)