Итак ... это ответ, к которому я пришел, и кое-что стоящее за ним:
Espresso (в частности, звонки на onView()
, onData()
, injectEvent
и Actions
) использует UiControllerImpl.loopMainThreadUntilIdle()
, чтобы дождаться, пока все "вызывающие холостые" сигналы будут ложными. Он проходит по AsyncTask, CompatAsyncTask и тому, что называется dynamicIdle
, чтобы все бездействовали.
Когда этот метод возвращает основной поток продолжается.
loopMainThreadUtilIdle()
проверяет IdleNotifier
, чтобы проверить состояние простоя каждого из этих трех элементов. Очевидно, что если вы хотите остановить эспрессо в ожидании AsyncTask, asyncIdle
представляет для вас особый интерес.
Классы IdleNotifier
передаются в UiControllerImpl
при его построении - это происходит через кинжал, поэтому вам нужно взглянуть на DaggerBaseLayerComponent
, который использует провайдеры, чтобы получить аргументы конструкции и передать их в UiControllerProvider для построения это.
Все во всех этих классах заперты очень плотно. Видимость метода и класса обычно защищена или является частной и финальной.
Единственным способом, который я нашел, было создание моего собственного класса Espresso.java (onView () и onData ()), в котором использовался пользовательский DaggerBaseLayerComponent, позволяющий мне использовать либо: моих собственных провайдеров, либо мой собственный UiController.
Я обнаружил, что это не решает всей проблемы. Существует еще один механизм, который необходимо закодировать - когда вы начинаете деятельность, в классе Instrumentation используется waitForIdleSync
. Обычно это тот Runner, который указан в вашем файле Gradle. Я создал свой собственный AndroidJUnitRunner и предоставил его в Gradle, чтобы я мог вернуться с waitForIdleSync
по команде.
И, наконец, в startActivitySync
в базовом классе Instrumentation он использует массив объектов ActivityWaiter
для удержания ваших вызовов launchIntent()
. Я не мог придумать разумного способа избежать этого, поэтому я обманул и создал этот метод в своем Runner:
public void clearActivityWaitQueue() {
Object mSync = Whitebox.getInternalState(this, "mSync");
List mWaitingActivities = Whitebox.getInternalState(this, "mWaitingActivities");
if (mSync != null && mWaitingActivities != null) {
mWaitingActivities.clear();
synchronized (mSync) {
mSync.notifyAll();
}
}
}
Он использует PowerMock, чтобы дать мне удобные методы Whitebox для установки внутреннего состояния Инструментовки:
// Used to give access to Whitebox
androidTestImplementation 'org.powermock:powermock-reflect:1.6.5'
И это все! Легко ли?
( Пожалуйста, скажите мне, что это проще, чем это и как !! )