使用 CountingIdlingResource 进行异步操作的仪器测试失败

Instrumentation test fails with Async operations using CountingIdlingResource

在我的仪器测试中,testZoomControls 总是在 CountingIdlingResource 递减之前执行并导致 map has not been initialized 异常。

怎么可能?

MapViewUiControlsTest.kt

@RunWith(AndroidJUnit4::class)
class MapViewUiControlsTest {

    private lateinit var mapView: MapView
    private lateinit var map: Map

    @Rule
    @JvmField
    val activityRule: ActivityTestRule<MapViewTestActivity> = ActivityTestRule(
        MapViewTestActivity::class.java
    )

    @Rule
    @JvmField
    val grantPermissionRule: GrantPermissionRule =
        GrantPermissionRule.grant(android.Manifest.permission.ACCESS_FINE_LOCATION)

    private lateinit var idlingResource: CountingIdlingResource

    @Before
    @UiThreadTest
    fun init() {
        MockitoAnnotations.initMocks(this)

        idlingResource = activityRule.activity.idlingResource

        idlingResource.registerIdleTransitionCallback({
            map = activityRule.activity.map
            mapView = activityRule.activity.mapView
        })

        IdlingRegistry.getInstance().register(idlingResource)

        activityRule.activity.init()
    }

    @After
    @UiThreadTest
    fun cleanup() {
        IdlingRegistry.getInstance().unregister(idlingResource)
    }

    @Test
    @UiThreadTest
    fun testZoomControls() {
        map.getMapOptions().zoomControlsEnabled = true
        Assert.assertEquals(View.VISIBLE, mapView.zoomControlsView.visibility)
    }

}

MapViewTestActivity.kt

val idlingResource = CountingIdlingResource("dummy_resource", true)

fun init() {
    idlingResource.increment()
    mapView.getMapAsync(onMapReadyCallback = object : OnMapReadyCallback {
        override fun onMapReady(map: Map) {
            this@MapViewTestActivity.map = map
            idlingResource.decrement()
        }
    })
}

你需要 Espresso.onView(..).check(..) 或类似的东西才能使这个 IdlingResource 有所不同。在这种情况下,Espresso 将等待所有 IdlingRsources 都空闲,然后继续执行下一行代码:

@Test
@UiThreadTest
fun testZoomControls() {
    //this will wait until your IdlingResource is idle
    Espresso.onView(<your map view matcher>).check(matches(isDisplayed()));

    map.getMapOptions().zoomControlsEnabled = true
    Assert.assertEquals(View.VISIBLE, mapView.zoomControlsView.visibility)
}