与Coroutines进行单位测试
#测试 #android #unittest #coroutines

Coroutines API已经在Android和Kotlin世界中带来了一些创新。我一直很喜欢将其尽可能简单的想法。这里有一个说法,“谁与谁交谈,犯了太多错误”,我认为这与Java的冗长以及并发世界有些相关。一遍又一遍地说并发并不简单,我不同意:您必须关心上下文,并行运行,取消,返回值等。

我希望我能在一个解释Kotlin Coroutines的of my previous articles中尽力而为,因此我将介绍它们的测试工具。

像往常一样,有些人可能仍然害怕测试,但我真的很有趣。但是,在谈论Coroutines时,没有新概念可以添加到软件测试中,只是定义了“默认” testCoroutinedispatcher,它只是一个coroutinedispatcher,它以相同的方式立即运行和懒惰的代码。换句话说,coroutinedispatcher的测试双重(不确定是假的)。

所以让我们测试。正如解释的那样,我们应该能够做到这一点,一旦我们在模块中具有依赖性:

testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.2'

之后,我们只需要添加一些小配置以开始我们的测试,如上所述:

@RunWith(JUnit4::class)
@ExperimentalCoroutinesApi //mark the class better, otherwise you should mark all variables and methods where coroutines testing is involved
class HomeRepositoryTest {
    private lateinit var homeRepository: HomeRepository
    private lateinit var someApi: SomeApi
    private val testDispatcher = TestCoroutineDispatcher() // the dispatcher

    @Before
    fun setUp() {
        //...... mocs and initialisations here
        Dispatchers.setMain(testDispatcher) //set the coroutine context
    }

    @After
    fun tearDown() {
        print("Test has finished")
        Dispatchers.resetMain() //reset
        testDispatcher.cleanupTestCoroutines() // clear all
    }
   }

注意:Coroutines测试API仍是实验性的,因此为了不注释使用@ExperimentalCoroutinesApi的所有变量和方法,只需注释正在测试的类(应该节省您的时间)。

之后,这里唯一的新事物是runBlockingTest子句(我喜欢以这种方式调用lambdas,但这是一种方法),这当然是模仿runblocking的。您应该能够将TestDisPatcher作为参数传递,但不是强制性的:

    @Test
    fun `my awful unit test should do something`() = runBlockingTest(testDispatcher) {
        `when`(rocket.readInt(GREGORIAN_DAY_KEY)).thenReturn(0)

        val day = homeRepository.getCurrentRegisteredDay() //this method is marked with suspend

        assertEquals(0, day)
    }

就是这样。

注意:如果您还不相信实验性API,那么即使不是太多建议这样做,您也可以自由进行测试(对于这种情况可能有些多余)。

结论

由于我已经提到并发很困难,而Coroutines使其变得简单,因此也应该有一个很好的工具,可以使测试简单。 Coroutines测试API是答案。有关documentation page中的依赖性的更多信息。

Stavro Xhardha。