Эспрессо и postDelayed


У меня есть действие, которое использует вызов postDelayed:

public class SplashActivity extends Activity {
    private Handler handler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(...);
        handler.postDelayed(new Runnable() { 
            public void run() { finish(); }
        }, 3000L);
    }
 }

Это работает при запуске приложения, и мне нужно перемещаться по нему и экрану входа в систему. Однако loopMainThreadUntilIdle UIController, похоже, не принимает во внимание лежащее в основе MessageQueue в обработчике. Таким образом, это действие завершается немедленно, пока в очереди еще есть сообщения.

onView(withId(R.id.splash_screen)).perform(new ViewAction() {
    @Override
    public Matcher<View> getConstraints() {
        return isAssignableFrom(View.class);
    }

    @Override
    public String getDescription() {
        return "";
    }

    @Override
    public void perform(final UiController uiController, final View view) {
        uiController.loopMainThreadUntilIdle();
    }
});

Я не могу понять, как блокировать, пока очередь не будет опустошена. Сам андроид мне мешает от выполнения многих вещей, которые я бы попытался (например, расширение обработчика и переопределение метода postDelayed и т. д...)

У кого-нибудь есть предложения о том, как обращаться с postDelayed?

Я бы предпочел избегать uiController.loopMainThreadForAtLeast, который кажется хаки (как нить.спать хотел)

1 9

1 ответ:

Когда Эспрессо ждет, он действительно принимает во внимание MessageQueue, но по-другому, чем вы думаете. Чтобы бытьпраздным , очередь должна быть либо пустой, , либо есть задачи, которые будут выполняться в течение более чем 15 миллисекунд с этого момента .

Вы можете проверить код самостоятельно, особенно метод loopUntil() в UiControllerImpl.java и файл QueueInterrogator.java. В последнем файле вы также найдете логику того, как Espresso проверяет MessageQueue (метод determineQueueState()).

Теперь, как решить ваш проблема? есть много способов:

  1. Используйте AsyncTask вместо Handler, спящий в фоновом потоке и выполняющий действия onPostExecute(). Это делает трюк, потому что эспрессо будет ждать окончания AsyncTask, но вам может не понравиться накладные расходы другого потока.

  2. Спите в своем тестовом коде, но вам уже не нравится этот подход.

  3. Напишите свой обычай IdlingResource: это общий механизм, позволяющий Эспрессо знать, когда что-то бездействует, чтобы он может запускать действия и утверждения. Для этого подхода вы могли бы:

    • Используйте класс CountingIdlingResource, который поставляется с эспрессо

    • Вызовите increment() , когда вы разместите свой runnable и decrement() внутри runnable после запуска вашей логики

    • Зарегистрируйте свой IdlingResource в тестовой установке и отмените его регистрацию в разрыве

См. также: docs and sample, другой пример