我有一个UI测试点击按钮,然后在其onClickListener中启动一个新的Activity。该测试检查是否发送了预期意图。
我的问题是,我想测试预期意图是否发送而不实际启动活动。因为我发现新活动初始化了它的状态,并且后续测试变得不稳定。
我知道有两个Espresso Intents api,intended
和intending
,但都无法满足我的需求。 intended
api实际上启动了目标活动,intending
api没有启动该活动,但它调用onActivityResult
回调,我也不想要。因为我担心onActivityResult
内的代码可能会导致另一种瑕疵。另外intending
没有断言是否发送了匹配意图,它只是在找到匹配意图时调用onActivityResult
回调,这意味着我必须检查是否调用了onActivityResult
!
有没有什么干净的方法可以达到我的目的?
答案 0 :(得分:10)
如果您想测试是否在没有实际启动活动的情况下发送预期意图,您可以通过使用activityResult捕获意图然后捕获活动来执行此操作:
Intent intent = new Intent();
ActivityResult intentResult = new ActivityResult(Activity.RESULT_OK,intent);
intending(anyIntent()).respondWith(intentResult);
onView(withId(R.id.view_id_to_perform_clicking)).check(matches(isDisplayed())).perform(click());
intended(allOf(hasComponent(ActivityToBeOpened.class.getName())));
这将捕获任何启动ActivityToBeOpened的尝试。如果您想要更具体,您还可以使用Extras捕获意图:
intended(allOf(hasComponent(ActivityToBeOpened.class.getName()), hasExtra("paramName", "value")));
希望有所帮助。
答案 1 :(得分:2)
Espresso的Intents
课程是一个简洁而方便的课程,但如果它不能满足您的需求,那么还有另一种选择。如果您使用AndroidJUnit4
测试运行器,则可以使用Instrumentaion
获取InstrumentationRegistry.getInstrumentation()
实例,然后您可以添加Instrumentation.ActivityMonitor
实例。
Instrumentation.ActivityMonitor am = new Instrumentation.ActivityMonitor("YOUR_ACTIVITY", null, true);
InstrumentationRegistry.getInstrumentation().addMonitor(am);
onView(withId(R.id.view_id_to_perform_clicking)).check(matches(isDisplayed())).perform(click());
assertTrue(InstrumentationRegistry.getInstrumentation().checkMonitorHit(am, 1));
ActivityMonitor
构造函数的第三个参数告诉我们要阻止活动启动。请注意,这种方法有其局限性。与Espresso Intents'相比。 rich Matcher support,您无法为ActivityMonitor
设置多个条件。
您可以在ApiDemos中找到多个样本,尤其是在ContactsSelectInstrumentation
课程中。
答案 2 :(得分:1)
实际上,您可以阻止任何启动外部或您自己活动的意图,但仍然使用丰富的Espresso Intents API:
Instrumentation.ActivityMonitor soloMonitor = solo.getActivityMonitor();
instrumentation.removeMonitor(soloMonitor);
IntentFilter filter = null;
// Block any intent
Instrumentation.ActivityMonitor monitor = instrumentation.addMonitor(filter, null, true);
instrumentation.addMonitor(soloMonitor);
// User action that results in an external browser activity being launched.
user.clickOnView(system.getView(R.id.callButton));
instrumentation.waitForIdleSync();
Intents.intended(Matchers.allOf(
IntentMatchers.hasAction(Matchers.equalTo(Intent.ACTION_VIEW)),
IntentMatchers.hasData(Matchers.equalTo(Uri.parse(url))),
IntentMatchers.toPackage(chromePackage)));
instrumentation.removeMonitor(monitor);
你能够做到这一点,因为即使你阻止它们,Espresso Intents仍会记录每个Intent和IntentMonitor回调。查看Espresso Intents的源代码,了解他们如何做到这一点。
如果您使用Robotium Solo框架,则需要在自己的ActivityMonitor
之前移动它们。否则只需跳过与此相关的行。