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