本博客将为上一篇博客Kotlin之协程(第二趴)——使用协程控制界面编写的代码编写测试。将使用kotlinx-coroutines-test
库测试在Dispatchers.Main
上运行的协程。
1、查看现有代码
打开androidTest
文件夹中的MainViewModelTest.kt
MainViewModelTest.kt
class MainViewModelTest {
@get:Rule
val coroutineScope = MainCoroutineScopeRule()
@get:Rule
val instantTaskExecutorRule = InstantTaskExecutorRule()
lateinit var subject: MainViewModel
@Before
fun setup() {
subject = MainViewModel(
TitleRepository(
MainNetworkFake("OK"),
TitleDaoFake("initial")
)
)
}
}
规则是一种在JUnit中进行测试之前和之后运行代码的方式。我们利用以下两个规则在设备外测试中测试MainViewModel:
InstantTaskExecutorRule
是一种JUnit规则,用于配置LiveData
以同步执行每项任务。MainCoroutineScopeRule
是此代码库中的自定义规则,用于将Dispatchers.Main
配置为使用kotlinx-coroutines-test
中的TestCoroutineDispatcher
。这样依赖,测试可以将用于测试的虚拟时钟拨快,并让代码可以使用单元测试中的Dispatchers.Main
。
在setup
方法中,系统使用测试虚构对象创建一个新的MainViewModel
实例。这些对象时在起始代码中提供的网络和数据库的虚构实现,以帮助在不使用时机网络或数据库的情况下编写测试。
对于此测试,只需要将一来虚拟对象来满足MainViewModel
的依赖项要求。
2、编写用于控制协程的测试
添加一项新的测试,以确保系统在用户点按主视图的一秒钟后更新点按计数: MainViewModelTest.kt
@Test
fun whenMainClicked_updatesTaps() {
subject.onMainViewClicked()
Truth.assertThat(subject.taps.getValueForTest()).isEqualTo("0 taps")
coroutineScope.advanceTimeBy(1000)
Truth.assertThat(subject.taps.getValueForTest()).isEqualTo("1 taps")
}
通过调用onMainViewClicked
,提供将启动我们刚刚创建的协程。此测试用于检查是否出现以下情况:
点按计数文字在系统调用onMainViewClicked
后保持"0 taps"不变,然后再1秒钟后更新为“1 taps”。
此测试使用虚拟时间控制onMainViewClicked
所启动的协程的执行。使用MainCoroutineScopeRule
,您可以暂停、恢复或控制在Dispatchers.Main
上启动的协程的执行。在这里,我们将调用advanceTieBy(1_000)
,这会导致主调度程序立即执行预定在1秒后恢复的协程。
此测试具有完全确定性,这意味着它将始终以相同的方式执行。此外,由于测试完全控制在Dispatchers.Main
上启动的协程的执行,因此无需等待一秒钟,即可设置值。
3、运行现有测试
- 右键点击编辑器中的类名称
MainViewModelTest
,以打开上下文菜单。 - 在上下文菜单中,选择
Run ‘MainViewModelTest'
-
- 今后运行测试时,您可以在工具栏中
按钮旁边的配置中选择此测试配置。默认情况下,此配置将称为 MainViewModelTest。
- 今后运行测试时,您可以在工具栏中
您应该会看到测试通过!实际运行时间应该比 1 秒钟短一些。