Issue
I am writing a UI test that goes to a Search screen, conducts a search, and clicks on an item to get to the details of that item. I get a crash on most, but not all of the items the automation test clicks on. I can see that the data loads but crashes while waiting for idle.
Code:
composeTestRule.waitForIdle()
Crash:
Caused by: java.util.concurrent.ExecutionException: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean androidx.compose.ui.node.LayoutNode.getNeedsOnPositionedDispatch$ui_release()' on a null object reference
at androidx.test.espresso.Espresso.onIdle(Espresso.java:35)
at androidx.test.espresso.Espresso.onIdle(Espresso.java:21)
at androidx.compose.ui.test.junit4.EspressoLink_androidKt.runEspressoOnIdle(EspressoLink.android.kt:92)
at androidx.compose.ui.test.junit4.EspressoLink.runUntilIdle(EspressoLink.android.kt:79)
at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.waitForIdle(ComposeUiTest.android.kt:308)
at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.access$waitForIdle(ComposeUiTest.android.kt:217)
at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$AndroidComposeUiTestImpl.waitForIdle(ComposeUiTest.android.kt:391)
at androidx.compose.ui.test.junit4.AndroidComposeTestRule.waitForIdle(AndroidComposeTestRule.android.kt:177)
Update: I found out that this crashes after "focusRequester.requestFocus()" in my layout, but only if there are items in the list that requests focus. i have checked that focusRequester is not null.
Update 2: I have uncovered that running "lazyListState.scrollToItem()" when the page loads causes this crash. Seems odd to me but, if i add a delay prior to that call, it works. Still seems like a hack though.
Solution
Fix: In my case i was using "lazyListState.scrollToItem()" inside the "onFocusChanged" modifier, which requires a coroutine. Taking that code out to a "launchedEffect" fixed this issue
So changing this
.onFocusChanged { event ->
if (event.isFocused) {
coroutineScope.launch {
lazyColumnState.scrollToItem(selectedItemIndex, 0)
}
}
}
To this
LaunchedEffect(key1 = hasFocus) {
if (hasFocus) {
coroutineScope.launch {
lazyColumnState.scrollToItem(selectedItemIndex, 0)
}
}
}
Answered By - BigApeWhat
Answer Checked By - Marie Seifert (JavaFixing Admin)