Espresso-Intents 是 Espresso 的扩展,它允许验证和存根由被测应用程序发送的 意图。它类似于 Mockito,但适用于 Android 意图。
如果您的应用将功能委托给其他应用或平台,您可以使用 Espresso-Intents 来专注于您自己的应用逻辑,同时假设其他应用或平台将正常运行。使用 Espresso-Intents,您可以匹配和验证您的传出意图,甚至可以提供存根响应来代替实际的意图响应。
在您的项目中包含 Espresso-Intents
在您应用的 app/build.gradle
文件中,在 dependencies
内部添加以下行
Groovy
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.6.1'
Kotlin
androidTestImplementation('androidx.test.espresso:espresso-intents:3.6.1')
Espresso-Intents 仅与 Espresso 2.1+ 和 Android 测试库的 0.3+ 版本兼容,因此请确保您也更新这些行
Groovy
androidTestImplementation 'androidx.test:runner:1.6.1' androidTestImplementation 'androidx.test:rules:1.6.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
Kotlin
androidTestImplementation('androidx.test:runner:1.6.1') androidTestImplementation('androidx.test:rules:1.6.1') androidTestImplementation('androidx.test.espresso:espresso-core:3.6.1')
编写测试规则
在编写 Espresso-Intents 测试之前,请设置一个 IntentsTestRule
。这是 ActivityTestRule
类的扩展,它使在功能性 UI 测试中轻松使用 Espresso-Intents API。一个 IntentsTestRule
在每个使用 @Test
注释的测试之前初始化 Espresso-Intents,并在每次测试运行后释放 Espresso-Intents。
以下代码段是 IntentsTestRule
的示例
Kotlin
@get:Rule val intentsTestRule = IntentsTestRule(MyActivity::class.java)
Java
@Rule public IntentsTestRule<MyActivity> intentsTestRule = new IntentsTestRule<>(MyActivity.class);
匹配
Espresso-Intents 提供了根据某些匹配条件拦截传出意图的能力,这些条件是使用 Hamcrest Matchers 定义的。Hamcrest 允许您
- 使用现有的意图匹配器:最简单的选项,几乎总是应该优先考虑。
- 实现您自己的意图匹配器:最灵活的选项。更多详细信息可以在 Hamcrest 教程 中“编写自定义匹配器”部分找到。
Espresso-Intents 提供了 intended()
和 intending()
方法,分别用于意图验证和存根。两者都采用 Hamcrest Matcher<Intent>
对象作为参数。
以下代码段显示了意图验证,它使用现有的意图匹配器,该匹配器匹配启动浏览器的传出意图
Kotlin
assertThat(intent).hasAction(Intent.ACTION_VIEW) assertThat(intent).categories().containsExactly(Intent.CATEGORY_BROWSABLE) assertThat(intent).hasData(Uri.parse("www.google.com")) assertThat(intent).extras().containsKey("key1") assertThat(intent).extras().string("key1").isEqualTo("value1") assertThat(intent).extras().containsKey("key2") assertThat(intent).extras().string("key2").isEqualTo("value2")
Java
assertThat(intent).hasAction(Intent.ACTION_VIEW); assertThat(intent).categories().containsExactly(Intent.CATEGORY_BROWSABLE); assertThat(intent).hasData(Uri.parse("www.google.com")); assertThat(intent).extras().containsKey("key1"); assertThat(intent).extras().string("key1").isEqualTo("value1"); assertThat(intent).extras().containsKey("key2"); assertThat(intent).extras().string("key2").isEqualTo("value2");
验证意图
Espresso-Intents 记录了试图从被测应用程序启动活动的 所有 意图。使用 intended()
方法,它类似于 Mockito.verify()
,您可以断言已看到给定的意图。但是,除非您 明确配置,否则 Espresso-Intents 不会存根对意图的响应。
以下代码段是一个示例测试,它验证但不存根对启动外部“电话”活动的传出意图的响应
Kotlin
@Test fun validateIntentSentToPackage() { // User action that results in an external "phone" activity being launched. user.clickOnView(system.getView(R.id.callButton)) // Using a canned RecordedIntentMatcher to validate that an intent resolving // to the "phone" activity has been sent. intended(toPackage("com.android.phone")) }
Java
@Test public void validateIntentSentToPackage() { // User action that results in an external "phone" activity being launched. user.clickOnView(system.getView(R.id.callButton)); // Using a canned RecordedIntentMatcher to validate that an intent resolving // to the "phone" activity has been sent. intended(toPackage("com.android.phone")); }
存根
使用 intending()
方法,它类似于 Mockito.when()
,您可以为使用 startActivityForResult()
启动的活动提供存根响应。这对于外部活动尤其有用,因为您无法操作外部活动的界面,也无法控制返回到测试中活动的 ActivityResult
。
以下代码片段实现了示例 activityResult_DisplaysContactsPhoneNumber()
测试,它验证当用户在被测应用程序中启动“联系人”活动时,将显示联系人电话号码。
构建在启动特定活动时要返回的结果。示例测试拦截发送到“联系人”的所有 Intent,并使用结果代码
RESULT_OK
,用有效的ActivityResult
替代它们的响应。Kotlin
val resultData = Intent() val phoneNumber = "123-345-6789" resultData.putExtra("phone", phoneNumber) val result = Instrumentation.ActivityResult(Activity.RESULT_OK, resultData)
Java
Intent resultData = new Intent(); String phoneNumber = "123-345-6789"; resultData.putExtra("phone", phoneNumber); ActivityResult result = new ActivityResult(Activity.RESULT_OK, resultData);
指示 Espresso 在对“联系人”意图的所有调用做出响应时提供存根结果对象。
Kotlin
intending(toPackage("com.android.contacts")).respondWith(result)
Java
intending(toPackage("com.android.contacts")).respondWith(result);
验证用于启动活动的动作是否产生了预期的存根结果。在本例中,示例测试检查在启动“联系人活动”时,电话号码 "123-345-6789" 是否被返回并显示。
Kotlin
onView(withId(R.id.pickButton)).perform(click()) onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber)))
Java
onView(withId(R.id.pickButton)).perform(click()); onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber)));
以下是完整的 activityResult_DisplaysContactsPhoneNumber()
测试。
Kotlin
@Test fun activityResult_DisplaysContactsPhoneNumber() { // Build the result to return when the activity is launched. val resultData = Intent() val phoneNumber = "123-345-6789" resultData.putExtra("phone", phoneNumber) val result = Instrumentation.ActivityResult(Activity.RESULT_OK, resultData) // Set up result stubbing when an intent sent to "contacts" is seen. intending(toPackage("com.android.contacts")).respondWith(result) // User action that results in "contacts" activity being launched. // Launching activity expects phoneNumber to be returned and displayed. onView(withId(R.id.pickButton)).perform(click()) // Assert that the data we set up above is shown. onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber))) }
Java
@Test public void activityResult_DisplaysContactsPhoneNumber() { // Build the result to return when the activity is launched. Intent resultData = new Intent(); String phoneNumber = "123-345-6789"; resultData.putExtra("phone", phoneNumber); ActivityResult result = new ActivityResult(Activity.RESULT_OK, resultData); // Set up result stubbing when an intent sent to "contacts" is seen. intending(toPackage("com.android.contacts")).respondWith(result); // User action that results in "contacts" activity being launched. // Launching activity expects phoneNumber to be returned and displayed. onView(withId(R.id.pickButton)).perform(click()); // Assert that the data we set up above is shown. onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber))); }
其他资源
有关在 Android 测试中使用 Espresso-Intents 的更多信息,请参考以下资源。
示例
- IntentsBasicSample:
intended()
和intending()
的基本用法。 - IntentsAdvancedSample: 模拟用户使用相机获取位图。