使用 Robolectric 测试实时数据

问题描述 投票:0回答:2

我有以下测试,检查活动是否通过视图模型正确地从存储库获取数据。

@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)
    }
}

问题是测试总是失败,但在调试中它正确通过,但是当我在断言中使用错误条件调试它时,弹出以下异常。

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,这可能是一个错误吗?

android robolectric android-livedata
2个回答
5
投票

我有同样的问题,并且能够使用 instantTaskExecutorRule 修复它。

您需要将以下依赖项添加到您的应用程序 buil.gradle 文件中:

testImplementation 'androidx.arch.core:core-testing:2.1.0'

并在您的测试中包含以下规则:

// Executes tasks in the Architecture Components in the same thread
@get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()

0
投票

问题是运行 UI 测试的线程正在完成而没有任何错误,而

assert
在不同的线程中运行。

您可以更改测试方法以保持线程直到它被运行 observeOnce 的线程释放:

@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)

article中的更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.