【问题标题】:How can I check the expected intent sent without actually launching activity in Espresso?如何在没有在 Espresso 中实际启动活动的情况下检查发送的预期意图?
【发布时间】:2016-09-14 09:07:26
【问题描述】:

我有一个 UI 测试,它单击一个按钮,然后在其 onClickListener 中启动一个新 Activity。测试检查是否发送了预期的意图。

我的问题是,我想测试是否发送了预期的意图而不实际启动活动。因为我发现新活动初始化了它的状态,这使得后续测试变得不稳定。

我知道有两个Espresso Intents API,分别是@987654322@@987654323@,但都不能满足我的需求。 intended API 实际上会启动目标活动,而intending API 不会启动该活动,但它会调用我也不想要的onActivityResult 回调。因为我担心onActivityResult 中的代码可能会导致另一个问题。

intending 也不会断言是否发送了匹配的意图。它只是在找到匹配的意图时调用onActivityResult回调,这意味着我必须检查是否调用了onActivityResult

有没有一种干净的方法来实现我想要的?

【问题讨论】:

    标签: android android-intent android-activity android-espresso android-instrumentation


    【解决方案1】:

    如果您想在不实际启动活动的情况下测试是否发送了预期的意图,您可以通过使用 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")));
    

    希望对您有所帮助。

    【讨论】:

      【解决方案2】:

      Espresso 的Intents 类是一个简洁方便的api,但是当它不能满足你的需要时,还有一个替代方案。如果你使用AndroidJUnit4测试运行器,你可以使用@987654322@获取@987654321@实例,然后你可以添加@987654323@实例。

      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 中找到几个示例,尤其是在@987654326@ 类中。

      【讨论】:

      • 有没有办法用 ActivityMonitor 测试传入 Intent 的额外内容?
      【解决方案3】:

      实际上,您可以阻止任何启动外部或您自己的活动的意图,但仍使用丰富的 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,它们仍会使用 IntentMonitor 回调记录每个 Intent。查看Espresso Intents 的源代码,了解他们是如何做到的。

      如果您使用Robotium Solo 框架,您需要将您自己的ActivityMonitor 移到他们之前。否则,请跳过与此相关的行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-06-03
        • 1970-01-01
        • 2015-03-07
        • 2013-11-11
        • 1970-01-01
        • 2016-06-27
        • 1970-01-01
        相关资源
        最近更新 更多