【问题标题】:Android Espresso Intents test randomly fail with ``init() must be called prior to using this method``Android Espresso Intents 测试随机失败,在使用此方法之前必须调用 init()
【发布时间】:2015-11-10 07:26:28
【问题描述】:

我目前正在努力将一个项目推入浓缩咖啡测试。我已阅读大量文档并按照给定的做法开始使用。

一切正常,但是,当涉及到 Intents 相关测试时,结果很奇怪。

大多数时候,测试在我的 Mac 中通过,但在我同事的 Windows 中失败(并非所有测试都失败)并显示失败消息 java.lang.IllegalStateException: init() must be called prior to using this method

很奇怪,如果我们在 Android Studio 中运行 Debug 测试,一步一步地流代码,它就通过了。

这里是测试代码:

@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityTest {

  @Rule public IntentsTestRule<MainActivity> mRule = new IntentsTestRule<>(MainActivity.class, true, false);

  AccountManager accountManager;
  MainActivity   activity;


  private void buildLoginStatus() throws AuthenticatorException {
    DanteApp app = (DanteApp) InstrumentationRegistry.getTargetContext().getApplicationContext();
    accountManager = app.getDanteAppComponent().accountManager();

    DoctorModel doctorModel = AccountMocker.mockDoctorModel();
    accountManager.save(doctorModel.doctor);
    accountManager.setAccessToken(doctorModel.access_token, false);
  }

  @Before public void before() throws Exception {
    buildLoginStatus();

    // must login
    assertThat(accountManager.hasAuthenticated(), is(true));

    activity = mRule.launchActivity(null);
    // block all of the outer intents
    intending(not(isInternal())).respondWith(new Instrumentation.ActivityResult(Activity.RESULT_OK, null));
  }

  @After public void tearDown() throws Exception {
    accountManager.delete();
  }

  // failed
  @Test public void testViewDisplay() throws Exception {

    // check tabhost is displayed
    onView(withClassName(equalTo(TabHost.class.getName()))).check(matches(isDisplayed()));

    // check toolbar is displayed
    onView(withClassName(equalTo(ToolBar.class.getName()))).check(matches(isDisplayed()));
  }

  // passed
  @Test public void testCallServiceHotline() throws Exception {
    // switch to the account tab layout
    onView(withChild(withText(R.string.account))).perform(click());
    // click account menu to make a service call
    onView(withId(R.id.contact)).perform(click());

    // check call start expectly
    intended(allOf(
        not(isInternal()),
        hasAction(Intent.ACTION_DIAL),
        hasData(Uri.parse("tel:" + activity.getString(R.string.call_service)))
    ));
  }


  // failed
  @Test public void testOpenSettingsUI() throws Exception {
    // stub all internal intents
    Intents.intending(isInternal())
        .respondWith(new Instrumentation.ActivityResult(Activity.RESULT_OK, null));

    onView(withChild(withText(R.string.account))).perform(click());
    onView(withId(R.id.setting)).perform(click());

    // check open settings activity successfully
    intended(anyOf(
        hasComponent(SettingActivity.class.getName())
    ));
  }
}

测试库版本(几乎所有依赖都是最新的,我们使用物理设备和模拟器来测试):

  • 规则:0.4.1
  • 跑步者:0.4.1
  • 浓缩咖啡-*:2.2.1
  • 支持-*:23.1.0

任何想法都值得赞赏。谢谢!

【问题讨论】:

    标签: android testing android-espresso


    【解决方案1】:

    两种解决方案:

    1. 使用 ActivityTestRule 代替 IntentsTestRule,然后在 @Before 和 @After 中分别手动调用 Intents.init() 和 Intents.release()。
    2. 编写自定义 IntentTestRule 并覆盖 beforeActivityLaunched() 以包含您的 AccountManager 逻辑。将 afterActivityFinished 用于您当前的 @After 逻辑。这也将允许您只使用默认的 IntentTestRule 构造函数。 (首选解决方案)

    为什么会这样:

    “最后一点无关紧要,使用新的 IntentsTestRule 时要小心。它不会初始化 Intents.init(),直到 Activity 启动后 (afterActivityLaunched())。” - Shameless plug to my own post (halfway down helpful visual)

    我认为您遇到了竞争条件,在您的 @Before 方法中,您正在执行 launchActivity() 然后 espresso 在实际创建活动之前尝试执行 intending(not(isInternal())).respondWith(new Instrumentation.ActivityResult(Activity.RESULT_OK, null));,这意味着未调用 afterActivityLaunched(),这表示Intents.init() 也不是,崩溃!

    希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      IntentsTestRule 派生自 ActivityTestRule,应该为您管理 Intents.init()Intents.release()

      但是,就我而言,IntentsTestRule 无法正常工作。所以我切换回ActivityTestRule 并在发送意图的测试之前调用Intents.init()Intents.release()

      更多信息请查看reference

      【讨论】:

      • 这是最干净、最直接的解决方案。
      猜你喜欢
      • 1970-01-01
      • 2018-02-11
      • 2016-10-30
      • 2017-08-20
      • 1970-01-01
      • 1970-01-01
      • 2012-07-20
      • 2019-06-04
      • 1970-01-01
      相关资源
      最近更新 更多