【问题标题】:Android Instrumentation blocked in coroutineAndroid Instrumentation 在协程中被阻止
【发布时间】:2018-09-27 20:22:49
【问题描述】:

我的活动有一个 EditText 和一个按钮。当按下按钮时,会调用一个长时间运行的函数。在此期间应该禁用 EditText。当函数完成后,应该重新启用 EditText。这在运行应用程序时工作正常,但是我编写了一个 Espresso 单元测试来测试这种行为似乎不正确。

长时间运行的功能似乎暂停了需要超过 3 秒才能运行的单元测试。长时间运行的功能完成后,单元测试将测试 EditText 是否已禁用,它不再是因为任务完成并且loading 变量设置回false

我希望单元测试随后启动该功能,因为它是在协程中运行的,它会继续到下一行检查 EditText 是否已禁用。

我尝试了 CommonPool、UI、启动、异步、延迟等的所有不同变体,但似乎没有得到正确的行为。

suspend fun getData(): String {
    // simulate network request delay
    delay(3000)                       
    return "Hello, world!"
}

fun onButtonClicked() {
    // data binding field to disable EditText
    loading = true 

    launch(CommonPool) {
        // make "network call"
        val data = getData().await()

        // reenable EditText
        loading = false
    }
}

@Test
fun disableEditText() {
    // check the EditText starts off enabled
    onView(withId(R.id.edit_text))
            .check(matches(isEnabled()))

    // click the Button to simulate the network call
    onView(withId(R.id.button))
            .perform(click())

    // check the EditText is disabled
    onView(withId(R.id.edit_text))
            .check(matches(not(isEnabled()))
}

【问题讨论】:

  • 可能有一些 IdlingResource 正在等待协程完成?

标签: android kotlin coroutine android-espresso


【解决方案1】:

一般来说,您不应处理视图内的任何逻辑(活动、片段等),而应在单独的逻辑处理程序(如 ViewModel、Presenter 或 ..)中完成。

您可以使用框架(如 Mockito 或 MockK)spy 您的活动,并模拟 getData() 方法以始终快速返回,这样您的测试用例就不需要等待它。

要使用 mockito 监视您的活动,您可以使用来自 this 答案的信息,并使用 when(activity.getData()).thenReturn("") 来模拟该方法。由于你在模拟一个协程,你需要使用runBlocking 来运行你的测试。

class MainActivityTest {
    internal var subject: MainActivity

    val activityFactory: SingleActivityFactory<MainActivity> =
        object : SingleActivityFactory<MainActivity>(MainActivity::class.java) {
            protected fun create(intent: Intent): MainActivity {
                subject = spy(getActivityClassToIntercept())
                return subject
            }
        }

    @Rule
    var testRule: ActivityTestRule<MainActivity> = ActivityTestRule(activityFactory, true, true)

    @Test
    fun sampleTest() = runBlocking<Unit> {
        `when`(subject.getData()).thenReturn("")
        //verify(subject).
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-16
    • 1970-01-01
    • 1970-01-01
    • 2015-08-31
    • 2015-12-14
    • 1970-01-01
    相关资源
    最近更新 更多