我正在努力将项目推向espresso测试。我已阅读了大量文档并按照给定的做法开始使用。
一切正常,但是,当谈到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 :(得分:29)
两种解决方案:
至于为什么会发生这种情况:
“最后在一个不相关的注释中,使用新的IntentsTestRule时要小心。它不会初始化Intents.init(),直到活动启动后(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()
isn' t叫,这意味着Intents.init()
都不会崩溃!
希望这有帮助。
答案 1 :(得分:7)
IntentsTestRule
源自ActivityTestRule
,应该为您管理Intents.init()
和Intents.release()
。
但是,就我而言,IntentsTestRule
无效。所以我在发送意图的测试之后切换回ActivityTestRule
并在Intents.init()
之前调用Intents.release()
。
有关详细信息,请参阅此reference。