Подтвердить что ты не робот

Получить текущую активность в эспрессо-андроиде

В случае теста, который пересекает несколько действий, существует ли способ получить текущую активность?

Метод getActivtiy() просто дает одно действие, которое было использовано для запуска теста.

Я попробовал что-то вроде ниже,

public Activity getCurrentActivity() {
    Activity activity = null;
    ActivityManager am = (ActivityManager) this.getActivity().getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
    try {
        Class<?> myClass = taskInfo.get(0).topActivity.getClass();
        activity = (Activity) myClass.newInstance();
    }
    catch (Exception e) {

    }
    return activity;
}

но я получаю нулевой объект.

4b9b3361

Ответ 1

В Espresso вы можете использовать ActivityLifecycleMonitorRegistry, но он официально не поддерживается, поэтому он может не работать в будущих версиях.

Вот как это работает:

Activity getCurrentActivity() throws Throwable {
  getInstrumentation().waitForIdleSync();
  final Activity[] activity = new Activity[1];
  runTestOnUiThread(new Runnable() {
    @Override
    public void run() {
      java.util.Collection<Activity> activities = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED);
      activity[0] = Iterables.getOnlyElement(activities);
  }});
  return activity[0];
}

Ответ 2

Если вам нужно всего лишь сделать проверку против текущего Activity, использование может сочетаться с одним эскизом эспрессо, чтобы проверить, что ожидаемое намерение было запущено:

intended(hasComponent(new ComponentName(getTargetContext(), ExpectedActivity.class)));

Espresso также покажет вам намерения, выпущенные между тем, если они не соответствуют вашим.

Единственная настройка, в которой вы нуждаетесь, - это заменить ActivityTestRule на IntentsTestRule в тесте, чтобы он отслеживал запуск намерений. И убедитесь, что эта библиотека находится в ваших зависимостях build.gradle:

androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.1'

Ответ 3

Мне нравится версия @Ryan, поскольку она не использует недокументированные внутренности, но вы можете записать это еще короче:

private Activity getCurrentActivity() {
    final Activity[] activity = new Activity[1];
    onView(isRoot()).check(new ViewAssertion() {
        @Override
        public void check(View view, NoMatchingViewException noViewFoundException) {
            activity[0] = (Activity) view.getContext();
        }
    });
    return activity[0];
}

Помните, что при выполнении тестов в Firebase Test Lab это не сработает. Это не работает с

java.lang.ClassCastException: com.android.internal.policy.DecorContext cannot be cast to android.app.Activity

Ответ 4

Если у вас есть единственное действие в вашем тестовом примере, вы можете сделать:

1. объявите тест Rule

@Rule
public ActivityTestRule<TestActivity> mActivityTestRule = new ActivityTestRule<>(TestActivity.class);

2. получите Activity:

mActivityTestRule.getActivity()

Это кусок пирога!

Ответ 5

public static Activity getActivity() {
    final Activity[] currentActivity = new Activity[1];
    onView(allOf(withId(android.R.id.content), isDisplayed())).perform(new ViewAction() {
        @Override
        public Matcher<View> getConstraints() {
            return isAssignableFrom(View.class);
        }

        @Override
        public String getDescription() {
            return "getting text from a TextView";
        }

        @Override
        public void perform(UiController uiController, View view) {
            if (view.getContext() instanceof Activity) {
                Activity activity1 = ((Activity)view.getContext());
                currentActivity[0] = activity1;
            }
        }
    });
    return currentActivity[0];
}

Ответ 6

build.gradle

androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2',
                {
            exclude group: 'com.android.support', module: 'support-annotations'
        })

И в вашем тестовом классе Instrumented

 @Rule
    public ActivityTestRule<MainActivity> intentsTestRule = new ActivityTestRule<>(MainActivity.class);

    MainActivity mainActivity;

    @Before
    public void setUp() throws Exception {
        mainActivity = intentsTestRule.getActivity(); //now Activity view gets created
        //Because Activity view creation happens in UI Thread, so all the test cases, here, are used by UI Thread
    }

Ответ 7

Принятый ответ может не работать во многих тестах эспрессо. Следующее работает с эспрессо версии 2.2.2 и Android-компилятором/целевым SDK 27, работающим на устройствах API 25:

@Nullable
private Activity getActivity() {
    Activity currentActivity = null;

    ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(RESUMED);
    Collection resumedActivities = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(RESUMED);
    if (resumedActivities.iterator().hasNext()){
        currentActivity = (Activity) resumedActivities.iterator().next();
    }
    return currentActivity;
}

Ответ 8

Решение, предложенное @lacton, не работало для меня, возможно, потому, что активность не была в состоянии, о котором сообщалось ActivityLifecycleMonitorRegistry.

Я даже попробовал Stage.PRE_ON_CREATE, пока не получил никакой активности.

Примечание. Я не мог использовать ActivityTestRule или IntentTestRule, потому что начал свою деятельность с помощью activitiy-alias и не имел смысла использовать фактический класс в тестах, когда Я хочу проверить, работает ли псевдоним.

Мое решение было подписано на изменения жизненного цикла через ActivityLifecycleMonitorRegistry и блокирование тестового потока до запуска активности:

// NOTE: make sure this is a strong reference (move up as a class field) otherwise will be GCed and you will not stably receive updates.
ActivityLifecycleCallback lifeCycleCallback = new ActivityLifecycleCallback() {
            @Override
            public void onActivityLifecycleChanged(Activity activity, Stage stage) {
                classHolder.setValue(((MyActivity) activity).getClass());

                // release the test thread
                lock.countDown();
            }
         };

// used to block the test thread until activity is launched
final CountDownLatch lock = new CountDownLatch(1);
final Holder<Class<? extends MyActivity>> classHolder = new Holder<>();
instrumentation.runOnMainSync(new Runnable() {
   @Override
    public void run() {
        ActivityLifecycleMonitorRegistry.getInstance().addLifecycleCallback(lifeCycleCallback);
     }
});

// start the Activity
intent.setClassName(context, MyApp.class.getPackage().getName() + ".MyActivityAlias");
context.startActivity(intent);
// wait for activity to start
lock.await();

// continue with the tests
assertTrue(classHolder.hasValue());
assertTrue(classHolder.getValue().isAssignableFrom(MyActivity.class));

Holder - это в основном объект-обертка. Вы можете использовать массив или что-нибудь еще, чтобы захватить значение внутри анонимного класса.