Как проверить ожидаемое намерение, отправленное без фактического запуска активности в Espresso?

У меня есть тест пользовательского интерфейса, который нажимает кнопку, а затем запускает новую активность в своем onClickListener. Тест проверяет, отправлено ли ожидаемое намерение или нет.

Моя проблема в том, что я хочу проверить, отправлено ли ожидаемое намерение без фактического запуска действия. Потому что я обнаружил, что новая активность инициализирует свое состояние и делает последующие тесты ненадежными.

Я знаю, что есть два Espresso Intent. api, то есть intended и intending, но оба не соответствуют моим потребностям. intended API фактически запускает целевую активность, а intending API не запускает активность, но вызывает onActivityResult обратный вызов, который мне тоже не нужен. Потому что я боюсь, что код внутри onActivityResult может вызвать очередную ненадежность. Также intending не утверждает, отправлено ли совпадающее намерение, он просто вызывает обратный вызов onActivityResult при обнаружении совпадающего намерения, что означает, что я должен проверить, вызывается ли onActivityResult или нет!

Есть ли чистый способ достичь того, чего я хочу?




Ответы (3)


Если вы хотите проверить, отправлено ли ожидаемое намерение без фактического запуска действия, вы можете сделать это, перехватив намерение с помощью 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")));

Надеюсь, это поможет.

person FOMDeveloper    schedule 20.10.2016

Класс Espresso Intents — это лаконичный и удобный API, но если он не соответствует вашим потребностям, есть альтернатива. Если вы используете средство запуска тестов 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 сообщает, что мы хотим заблокировать запуск активности. Обратите внимание, что этот подход имеет свои ограничения. В отличие от богатых Поддержка Matcher. Вы не можете установить несколько условий для ActivityMonitor.

Вы можете найти несколько примеров в ApiDemos, особенно в классе ContactsSelectInstrumentation. .

person 김준호    schedule 14.09.2016
comment
Есть ли способ проверить дополнительные функции, переданные в Intent с помощью ActivityMonitor? - person Vincent_Paing; 20.02.2018

На самом деле, вы можете заблокировать любое намерение запустить внешнюю или собственную активность, но при этом использовать богатый API намерений Espresso:

    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 Intent по-прежнему записывает каждое намерение с помощью IntentMonitor, даже если вы их заблокируете. Посмотрите исходный код Espresso Intents о том, как они это делают.

Если вы используете фреймворк Robotium Solo, вам нужно переместить свой собственный ActivityMonitor перед их. В противном случае просто пропустите строки, связанные с этим.

person Bogdan Kornev    schedule 25.01.2018