@UiThreadTest annotation not working in wrting test for a fragment

Viewed 99

I wrote a test as below for a fragment that shows a list of comments

@RunWith(AndroidJUnit4::class)
class CommentListFragmentTest {


  @Rule
  @JvmField
  var instantExecutorRule = InstantTaskExecutorRule()

  private lateinit var mockedViewModel: CommentListViewModel
  private val mockNavController = mock<NavController>()

  private lateinit var commentListFragment: CommentListFragment

  @Before
  fun setup() {

    mockedViewModel = mock(CommentListViewModel::class.java)

    val scenario = launchFragmentInContainer(themeResId = R.style.AppTheme) {
        CommentListFragment().apply {

            commentListFragment = this
            viewModelFactory = ViewModelUtil.createFor(mockedViewModel)

            this.viewLifecycleOwnerLiveData.observeForever { viewLifecycleOwner ->
                if (viewLifecycleOwner != null) {
                    // The fragment’s view has just been created
                    Navigation.setViewNavController(this.requireView(), mockNavController)
                }
            }
        }
    }

    scenario.onFragment { fragment ->
        Navigation.setViewNavController(fragment.requireView(),mockNavController )
    }
  }

  @Test
  @UiThreadTest
  fun loadCommentsList() {

    val commentList: MutableList<Comment> = ArrayList()
    commentList.add(mock(Comment::class.java))
    commentList.add(mock(Comment::class.java))
    commentListFragment.render(CommentListUiModel.SetupList(commentList))

    Espresso.onView(withId(R.id.progress_bar))
         .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
    Espresso.onView(withId(R.id.recycler_view))
         .check(RecyclerViewItemCountAssertion(2))
    Espresso.onView(withId(R.id.emptyCommentList))
         .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
  }
}

and I got exception when calling a method of fragment in test method:

java.lang.IllegalStateException: Method cannot be called on the main application thread (on: main)
at androidx.test.internal.util.Checks.checkState(Checks.java:107)
at androidx.test.internal.util.Checks$1.checkNotMainThread(Checks.java:146)
at androidx.test.internal.util.Checks.checkNotMainThread(Checks.java:126)
at androidx.test.core.app.ActivityScenario.launchInternal(ActivityScenario.java:226)
at androidx.test.core.app.ActivityScenario.launch(ActivityScenario.java:209)
at androidx.fragment.app.testing.FragmentScenario.internalLaunch(FragmentScenario.java:299)
at androidx.fragment.app.testing.FragmentScenario.launchInContainer(FragmentScenario.java:282)
at com.beroozresaan.android.ui.productComment.list.CommentListFragmentTest.setup(CommentListFragmentTest.kt:111)

but when I use like below it works:

@Rule
@JvmField
var uiThreadTestRule = UiThreadTestRule()
@Test
fun loadCommentsList() {

    uiThreadTestRule.runOnUiThread {
        val commentList: MutableList<Comment> = ArrayList()
        commentList.add(mock(Comment::class.java))
        commentList.add(mock(Comment::class.java))
        commentListFragment.render(CommentListUiModel.SetupList(commentList))
    }

    Espresso.onView(withId(R.id.progress_bar))
         .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
    Espresso.onView(withId(R.id.recycler_view))
         .check(RecyclerViewItemCountAssertion(2))
    Espresso.onView(withId(R.id.emptyCommentList))
         .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.GONE)))

}

I want replace runOnUiThread with @UiThreadTest annotation because UiThreadTestRule deprecated, it seems @UiThreadTest not working, what's the problem? did I do something wrong?

0 Answers
Related