android-intent - Espresso-Intents - 匹配器和 stub

标签 android-intent android-espresso

我的应用程序偏好设置中有一个发送反馈。它应该打开一个选择器和一个新的意图,以发送包含提供的电子邮件地址、主题和文本模板的电子邮件。这部分仅适用于模拟器和物理设备:

prefButtonSendFeedback?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
            val emailIntent = Intent(Intent.ACTION_SENDTO)
            emailIntent.type = "text/plain"
            emailIntent.data = Uri.parse("mailto:")
            emailIntent.putExtra(Intent.EXTRA_EMAIL, arrayOf(getString(R.string.send_feedback_email_address)))
            emailIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.send_feedback_email_subject))
            emailIntent.putExtra(Intent.EXTRA_TEXT, getString(R.string.send_feedback_email_content_template))
            context?.startActivity(Intent.createChooser(emailIntent, getString(R.string.send_feedback_intent_name)))
            true
        }

我还针对这种情况进行了 Espresso 测试:

    @Test fun clickOnFeedbackActionMenuItem_StartsFeedbackFragment() {
        launchFragmentInContainer<SettingsFragment>()

        Intents.init()

        intending(
            hasAction(Intent.ACTION_CHOOSER)
        ).respondWith(
            ActivityResult(Activity.RESULT_OK, null)
        )

        // Press on Feedback navigation item
        onView(withId(androidx.preference.R.id.recycler_view))
            .perform(
                actionOnItem<RecyclerView.ViewHolder>(
                    hasDescendant(withText(R.string.pref_send_feedback)), click()
                )
            )

        val emailIntent = allOf(
            hasAction(Intent.ACTION_SENDTO),
            hasData(Uri.parse("mailto:")),
            hasExtra(Intent.EXTRA_EMAIL, arrayOf(withText(R.string.send_feedback_email_address))),
            hasExtra(Intent.EXTRA_SUBJECT, withText(R.string.send_feedback_email_subject)),
            hasExtra(Intent.EXTRA_TEXT, withText(R.string.send_feedback_email_content_template))
        )

        val expectedIntent = allOf(
            hasAction(Intent.ACTION_CHOOSER),
            hasExtra(equalTo(Intent.EXTRA_INTENT), emailIntent),
            hasExtra(equalTo(Intent.EXTRA_TITLE), withText(R.string.send_feedback_intent_name))
        )

        intended(expectedIntent)

        Intents.release()
    }

我的问题总体上与 How to stub Intent.createChooser Intent using Espresso 中的问题类似。

  • 使用代码中的匹配器时出现错误:
androidx.test.espresso.base.DefaultFailureHandler$AssertionFailedWithCauseError: Wanted to match 1 intents. Actually matched 0 intents.

IntentMatcher: (has action: is "android.intent.action.CHOOSER" and has extras: has bundle with: key: "android.intent.extra.INTENT" value: (has action: is "android.intent.action.SENDTO" and has data: is <mailto:> and has extras: has bundle with: key: is "android.intent.extra.EMAIL" value: is [<with string from resource id: <3134850762>>] and has extras: has bundle with: key: is "android.intent.extra.SUBJECT" value: is <with string from resource id: <2131820702>> and has extras: has bundle with: key: is "android.intent.extra.TEXT" value: is <with string from resource id: <2131820701>>))

Matched intents:[]

Recorded intents:
-Intent { act=android.intent.action.CHOOSER (has extras) } handling packages:[[android]], extras:[Bundle[{android.intent.extra.INTENT=Intent { act=android.intent.action.SENDTO dat=mailto: (has extras) }, android.intent.extra.TITLE=Send Feedback:}]])

  • 当我只有几个匹配器时,测试是绿色的 - 添加任何其他失败测试:
        val emailIntent = allOf(
            hasAction(Intent.ACTION_SENDTO),
            hasData(Uri.parse("mailto:")),
        )

        val expectedIntent = allOf(
            hasAction(Intent.ACTION_CHOOSER),
            hasExtra(equalTo(Intent.EXTRA_INTENT), emailIntent),
        )
  • 我还使用了真值断言和调试器
        val receivedIntent: Intent = Iterables.getOnlyElement(Intents.getIntents())
        assertThat(receivedIntent).hasAction(Intent.ACTION_CHOOSER) ### here is a breakpoint

它向我表明,我的意图包含我需要的所有附加内容(主题、地址和文本) - 我删除了不必要的值:

receivedIntent =
  (...)
  mAction = "android.intent.action.CHOOSER"
  (..)
  mExtras = 
    mMap = 
      value[0] = 
        mAction = "android.intent.action.SENDTO"
        mData = "mailto:"
        mExtras = 
          mMap =
            value[0] = "App Feedback"
            value[1] = "Add here any bugs, issues or ideas about App"
            value[2] =
              0 = "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c8a1a6aea788adb0a9a5b8a4ade6aba7a5" rel="noreferrer noopener nofollow">[email protected]</a>"
      value[1] = "Send Feedback:"

我的问题是,我的匹配器出了什么问题 - 对我来说它们看起来不错:

  • 选择器有额外的意图和标题
  • 电子邮件意图包含电子邮件地址、主题和文本

此外,我不确定 intending() 是如何工作的 - 我假设在我的代码中使用它不会在测试期间运行真正的 Intent。所以它不会运行电子邮件客户端。我错了 - 它运行了,但如果我使用 Intents.release(),如果没有它,所有下一个测试都会挂起。

最佳答案

因此,当我深入研究网络资源时,我发现了更复杂的 Espresso 匹配器:

        val expectedIntent = allOf(
            hasAction(Intent.ACTION_CHOOSER),
            hasExtra(
                equalTo(Intent.EXTRA_INTENT),
                allOf(
                    hasAction(Intent.ACTION_SENDTO),
                    hasData(Uri.parse("mailto:")),
                    hasExtra(
                        `is`(Intent.EXTRA_TEXT),
                        `is`("Add here any bugs, issues or ideas about App")
                    ),
                    hasExtra(
                        `is`(Intent.EXTRA_EMAIL),
                        `is`(arrayOf("<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="21484f474e614459404c514d440f424e4c" rel="noreferrer noopener nofollow">[email protected]</a>"))
                    ),
                    hasExtra(
                        `is`(Intent.EXTRA_SUBJECT),
                        `is`("App Feedback")
                    )
                )
            ),
            hasExtra(
                `is`(Intent.EXTRA_TITLE),
                `is`("Send Feedback:")
            )
        )

        intended(expectedIntent)

它确实有效。

我还是不明白其中的区别,所以如果有人可以向我解释一下......

我不知道为什么这个有效:

            hasExtra(
                `is`(Intent.EXTRA_TITLE),
                `is`("Send Feedback:")
            )

而这个不是:

            hasExtra(
                `is`(Intent.EXTRA_TITLE),
                 withText(R.string.send_feedback_intent_name)
            )

关于android-intent - Espresso-Intents - 匹配器和 stub ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63546419/

相关文章:

android - 如何将 ArrayList<CustomeObject> 从一个 Activity 传递到另一个 Activity ?

android - 使用 Espresso 验证弹出菜单中的项目

android - 用 Espresso 点击 EditText 的 drawable 右边

android - Bundle extras = data.getExtras(); 上的 java.lang.NullPointerException;

java - 在Android中调用一个变量的Intent

Android 隐式 Intent 验证

android - 检查 Android Espresso 框架中的 DatePicker 日历值

android - Espresso 测试 : Accessing Variables

android - Espresso 在某些测试中随机卡住

android - 一个 Activity 的两个发射器