Тестирование ливата с помощью Robolectric - PullRequest
0 голосов
/ 30 июня 2019

У меня есть следующий тест, который проверяет, правильно ли активность получает данные из репозитория через viewmodel.

@Config(application = TestApplication::class)
@RunWith(RobolectricTestRunner::class)
@LooperMode(LooperMode.Mode.PAUSED)
class BusinessTests {
    private lateinit var viewModel: BusinessCollectionViewModel
    private lateinit var activity: BusinessCollectionVerticalActivity
    private lateinit var observer: Observer<Triple<NetworkState, PagedList<Edge<Business>>, TimeTracking?>>

    @Before
    fun setUp() {
        observer = mock()
    }

    @Test
    fun givenBusinessMock_whenVerticalCollection_thenBusinessVerticalWith2Items() {

        val activityScenario = ActivityScenario.launch(BusinessCollectionVerticalActivity::class.java)
        activityScenario.onActivity {
            activity = it
        }

        viewModel = ViewModelProviders.of(activity)[BusinessCollectionViewModel::class.java]

        viewModel.data.observeForever(observer)
        assert(viewModel.data.value?.second?.size == 2)
    }
}

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

java.lang.Exception: Main looper has queued unexecuted runnables. This might be the cause of the test failure. You might need a shadowOf(getMainLooper()).idle() call.

Это действительно странное поведение, и я не знаю, что делать.И, конечно, я пытался добавить shadowOf (getMainLooper ()). Idle () перед наблюдением.

Я использую последнюю версию robolectric 4.3, может ли это быть ошибкой?

1 Ответ

0 голосов
/ 30 июня 2019

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

Вы можете изменить свой тестовый метод так, чтобы он удерживал поток до тех пор, пока он не будет освобожден потоком, который запускает наблюдение:

@Test
fun givenBusinessMock_whenVerticalCollection_thenBusinessVerticalWith2Items() {

    val syncObject = Object()

    val activityScenario = ActivityScenario.launch(BusinessCollectionVerticalActivity::class.java)
    activityScenario.onActivity {
        activity = it
    }

    viewModel = ViewModelProviders.of(activity)[BusinessCollectionViewModel::class.java]

    viewModel.data.observeOnce {
        assert(it.second.size == 2)

        synchronized (syncObject) {
            syncObject.notify()
        }
    }

    synchronized (syncObject) {
        syncObject.wait()
    }
}

Если вы хотите лучше подходить, вы можете наблюдать за Forever в ваших данных и проверять значение:

var observer: Observer<?> // replace ? by your type
viewModel.data.observeForever(observer)
assert(viewModel.data.value.second.size == 2)

Подробнее в этой статье .

...