我该如何在Android Espresso测试中测试setResult()方法?

15

有没有好的方法可以在Android Espresso测试中测试结果代码和数据?我正在使用Espresso 2.0。

假设我有一个名为BarActivity.classActivity,在执行某些操作后,使用适当的载荷调用setResult(int resultCode, Intent data)

我想编写一个测试用例来验证resultCodedata。然而,由于setResult()是一个final方法,我无法覆盖它。

我考虑了一些选项:

  • 定义一个新的方法,如setActivityResult(),只需使用它,以便可以拦截等...
  • 编写一个仅供测试的TestActivity,它将在BarActivity上调用startActivityForResult()并在TestActivity.onActivityResult()中检查结果

试图想一想哪个更少的两个罪恶,或者是否有任何其他建议来测试这个。 有什么建议吗? 谢谢!


这里有一个关于选项2的部分解决方案:https://product.reverb.com/2016/03/12/testing-android-activity-results/ 然而,它并不完整,至少我没能让它工作。 - friedger
4个回答

21

如果您同时切换到最新的Espresso版本3.0.1,则可以使用ActivityTestRule并像这样获取Activity结果:

assertThat(rule.getActivityResult(), hasResultCode(Activity.RESULT_OK));
assertThat(rule.getActivityResult(), hasResultData(IntentMatchers.hasExtraWithKey(PickActivity.EXTRA_PICKED_NUMBER)));

你可以在这里找到一个工作示例。


1
只要你能升级到3.0.1版本,这绝对是最干净的方法。 - skeeve
3
如果无法解决 hasResultCodehasResultData,请在 build.gradle 中添加 androidTestCompile 'com.android.support.test.espresso:espresso-contrib:3.0.1' - Paglian
你救了我的一天。谢谢! - Yuri Popiv

5
如果您想升级到2.1版,则可以查看Espresso-Intents:https://google.github.io/android-testing-support-library/docs/espresso/intents/index.html。通过使用intending API(Mockito.when的姊妹函数),您可以为使用startActivityForResult启动的活动提供响应。这意味着当特定活动被启动时(在您的情况下是BarActivity类),可以构建并返回任何结果。请参考此处的示例: https://google.github.io/android-testing-support-library/docs/espresso/intents/index.html#intent-stubbing以及我的回答(链接) 在一个类似问题的解释(但涉及联系人获取活动)。我展示了如何构建一个结果并将其发送回调用startActivityForResult的 Activity。

3
我不明白如何使用Espresso-Intents测试setResult方法。你能否解释一下? - friedger

1
这对我来说可行:

这适用于我:


@Test
    fun testActivityForResult(){

        // Build the result to return when the activity is launched.
        val resultData = Intent()
        resultData.putExtra(KEY_VALUE_TO_RETURN, true)

        // Set up result stubbing when an intent sent to <ActivityB> is seen.
        intending(hasComponent("com.xxx.xxxty.ActivityB")) //Path of <ActivityB>
            .respondWith(
                Instrumentation.ActivityResult(
                    RESULT_OK,
                    resultData
                )
            )

        // User action that results in "ActivityB" activity being launched.
        onView(withId(R.id.view_id))
            .perform(click())

      // Assert that the data we set up above is shown.
     onView(withId(R.id.another_view_id)).check(matches(matches(isDisplayed())))
    }


假设在 onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) 上有以下验证:

if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) {

    data?.getBooleanExtra(KEY_VALUE_TO_RETURN, false)?.let {showView ->
                if (showView) {
                 another_view_id.visibility = View.VISIBLE
                }else{
                 another_view_id.visibility = View.GONE
                 }
            }
        }

我按照以下指南作为参考:https://developer.android.com/training/testing/espresso/intents,同时我也不得不在上述链接的末尾检查这些链接https://github.com/android/testing-samples/tree/master/ui/espresso/IntentsBasicSamplehttps://github.com/android/testing-samples/tree/master/ui/espresso/IntentsAdvancedSample

0

如果你正在使用ActivityScenario(或者ActivityScenarioRule),这是Android开发文档中的当前推荐方法(参见测试应用程序的活动页面),那么ActivityScenario类提供了一个getResult()方法,你可以按照以下方式进行断言:

@Test
fun result_code_is_set() {
    val activityScenario = ActivityScenario.launch(BarActivity::class.java)

    // TODO: execute some view actions which cause setResult() to be called

    // TODO: execute a view action which causes the activity to be finished

    val activityResult = activityScenario.result

    assertEquals(expectedResultCode, activityResult.resultCode)
    assertEquals(expectedResultData, activityResult.resultData)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接