如何测试LiveData.asFlow().collect()并可靠地验证其中的方法调用?

问题描述 投票:0回答:1

我正在尝试测试一个类,该类采用

LiveData
对象,将其转换为流,收集它,并根据结果执行操作。

它在主代码中按预期工作,但我不知道如何测试它。看起来

collect
内的代码块发生的验证从未达到,并且测试错误地通过了。

这是我的设置:

class LiveDataClass {

    fun liveData(): LiveData<Boolean> {
        return MutableLiveData(true)
    }

    fun doSomething() {}

    fun decoyMethod() {} // to verify if it's called in the test, just to make it fail
}

收集流量的类:

class FlowClass(private val liveDataClass: LiveDataClass) {

    suspend fun doSomethingWhenLiveDataIsTrue() {
        liveDataClass.liveData().asFlow().collect {
            if (it) {
                println("Inside the collection")
                liveDataClass.doSomething() // we reach the code here in the test
            }
        }
    }
}

还有测试 - 我已经查看了多个设置示例以避免错误,即使此测试通过,并且我看到

liveDataClass.doSomething()
被调用,验证也从未发生。

我验证

liveDataClass.decoyMethod()
是否曾经被调用过(事实上并没有)并且测试仍然没问题......

class FlowClassTest {

    @get:Rule
    val instantTaskExecutorRule: TestRule = InstantTaskExecutorRule()

    private val dispatcher = StandardTestDispatcher()
    private val testScope = TestScope(dispatcher)

    @Before
    fun setUp() {
        Dispatchers.setMain(dispatcher)
    }

    @After
    fun tearDown() {
        Dispatchers.resetMain()
    }

    @Test
    fun test() = runTest {
        testScope.launch {

            println("Starting up the test case")
            val liveDataClass: LiveDataClass = mockk {
                every { liveData() } returns MutableLiveData(true)
                every { doSomething() } answers {
                    println("TEST - Doing something")
                }
            }

            val flowClass = FlowClass(liveDataClass)
            flowClass.doSomethingWhenLiveDataIsTrue()

            verify { // never happens and the test passes even though it shouldn't!
                println("Verifying")
                liveDataClass.decoyMethod()
            }
        }
    }
}

如何设置此测试,使其真正有用并正确验证调用?

android kotlin kotlin-coroutines android-livedata kotlin-flow
1个回答
0
投票

您正在使用 runTest 将测试作为协程运行。在此块内,您将使用 testScope.launch 启动另一个协程。这个嵌套协程是不必要的,可以删除。

尝试以下方法

@Test
fun test() = runTest {
    println("Starting up the test case")
    val liveDataClass: LiveDataClass = mockk {
        every { liveData() } returns MutableLiveData(true)
        every { doSomething() } answers {
            println("TEST - Doing something")
        }
    }

    val flowClass = FlowClass(liveDataClass)
    flowClass.doSomethingWhenLiveDataIsTrue()

    verify { 
        println("Verifying")
        liveDataClass.doSomething() // Verify that this method was called
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.