使用单元测试支持清理Kotlin中的协程

一段时间以来,我们正在与Kotlin合作,而我们目前正在关注的一件事情是使用Coroutines来处理我们想要运行异步的操作。

虽然示例的用法是清楚的,这是有效的,我有一些问题整合在一个干净的方式在我们的架构。 当看一个方法的领域为焦点的类的实现,这个想法是,它很容易阅读,有尽可能少的异步功能“噪音”。 我知道我不能有异步,没有实际使用它。 所以写这样的东西是我想要的:

val data = someService.getData().await() // work with data 

但是这是我想要阻止的:

 launch(UI) { val data val job = async(CommonPool) { data = someService.getData() } job.await() // work with data } 

那么,我想配对这些领域为重点的类的实际单元测试,但我真的不能得到这个工作。 我们来看一个例子:

 // Some dependency doing heavy work class ApiClient { suspend fun doExpensiveOperation(): String { delay(1000) return "Expensive Result Set" } } // Presenter Class class Presenter(private val apiClient: ApiClient, private val view: TextView) { private lateinit var data: String fun start() { log("Starting Presenter") runBlocking { log("Fetching necessary data") data = apiClient.doExpensiveOperation() log("Received necessary data") } workWithData() log("Started Presenter") } fun workWithData() { log(data) } private fun log(text: String) { view.append(text+"\n") } } // In an Activity val presenter = Presenter(ApiClient(), someTextView) presenter.start() 

这工作(截图: https : //imgur.com/a/xG9Xw )。 现在让我们看看测试。

 class PresenterTest { // ... Declared fields @Before fun setUp() { // Init mocks (apiClient, textView) MockitoAnnotations.initMocks(this) // Set mock responses runBlocking { given(apiClient.doExpensiveOperation()).willReturn("Some Value") } presenter = Presenter(apiClient, textView) } @Test @Throws(Exception::class) fun testThat_whenPresenterStarts_expectedResultShows() { // When presenter.start() // Then Mockito.verify(textView).text = "Some Value\n" } } 

现在这个测试并不理想,但是不管怎样,它甚至从来没有达到可以验证事情按预期工作的程度,因为lateinit var数据没有被初始化。 现在最终我们的领域类的美学和可读性只是我想走多远,我有一些实际的工作例子,我很高兴。 但是使我的测试工作似乎是具有挑战性的。

现在在网上有一些关于这种东西的不同的报道,但是没有任何东西真正适合我。 这个( https://medium.com/@tonyowen/android-kotlin-coroutines-unit-test-16e984ba35b4 )似乎很有意思,但是我不喜欢为主持人启动一个上下文的调用类的想法,因为在有一个依赖,做一些异步工作。 虽然作为一个抽象的想法,我喜欢“嘿,主持人,无论你做什么,在UI上下文中向我回报”这个想法,但是我觉得这是一个修复工作的方法,导致共享关注不同对象之间的异步功能。

无论如何,我的问题是:摆脱这些简短的例子,有没有人有任何关于如何在更大的体系结构中集成协同程序的指针,还有工作单元测试? 对于那些使我改变观察方式的观点,我也非常开放,因为这是一个不同的层面上的说服力,而不是“如果你想让事情发挥作用,你必须牺牲”。 这个问题不仅仅是作为例子的工作,因为这只是一个孤立的例子,而我正在寻找一个大项目中真正的可靠的整合。

期待您的意见。 提前致谢。