Artur A
Artur A

Reputation: 297

Test fails with recyclerview item

I don't know how to fix this exception I want to test if recyclerview item layout textview matches with the provided text or not? What is wrong ? and for RecyclerView matcher I am using https://gist.github.com/baconpat/8405a88d04bd1942eb5e430d33e4faa2 Here is layout.xml

<androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/layout_root"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/image"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:scaleType="centerCrop"
            app:imageUrl="@{imageUrl}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.05"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/title_herobanner"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/margin_small"
            android:ellipsize="end"
            android:text="@{title}"
            android:textSize="@dimen/text_large"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:text_color="@{theme.primaryTextColor}" />
    </androidx.constraintlayout.widget.ConstraintLayout>

and here is my test


@RunWith(AndroidJUnit4::class)
class HomeFragmentTest {

  @get:Rule
  val activityRule = ActivityTestRule(SingleFragmentActivity::class.java, true, true)

  @get:Rule
  val dataBindingIdlingResourceRule = DataBindingIdlingResourceRule(activityRule)

  private lateinit var viewModel: HomeViewModel
  private val contentRow = MutableLiveData<List<ContentRow>>()
  private val errorMessage = MutableLiveData<String>()
  private val homeFragment = TestHomeFragment()

  @Before
  fun init() {
    viewModel = Mockito.mock(HomeViewModel::class.java)
    Mockito.`when`(viewModel.contentRows).thenReturn(contentRow)
    Mockito.`when`(viewModel.errorMessageData).thenReturn(errorMessage)
    homeFragment.viewModelFactory = ViewModelUtil.createFor(viewModel)
    activityRule.activity.setFragment(homeFragment)
  }


  @Test
  fun loadResults() {
    contentRow.postValue(TestUtil.createContentRows())
    Espresso.onView(listMatcher().atPositionOnView(0, R.id.title_herobanner))
        .check(ViewAssertions.matches(ViewMatchers.withText("WE BRING")))
  }

  private fun listMatcher(): RecyclerViewMatcher {
    return RecyclerViewMatcher(R.id.list_herobanner)
  }

  class TestHomeFragment : HomeFragment() {
    override fun onAttach(context: Context) {
      super.onAttach(context)
    }

    override fun injectMembers() {
    }
  }
}

and here is RecyclerViewMatcher.java

class RecyclerViewMatcher(private val recyclerViewId: Int) {

    fun atPosition(position: Int): Matcher<View> {
        return atPositionOnView(position, -1)
    }

    fun atPositionOnView(position: Int, targetViewId: Int): Matcher<View> {
        return object : TypeSafeMatcher<View>() {
            var resources: Resources? = null
            var childView: View? = null

            override fun describeTo(description: Description) {
                var idDescription = recyclerViewId.toString()
                if (this.resources != null) {
                    idDescription = try {
                        this.resources!!.getResourceName(recyclerViewId)
                    } catch (var4: Resources.NotFoundException) {
                        "$recyclerViewId (resource name not found)"
                    }
                }

                description.appendText("RecyclerView with id: $idDescription at position: $position")
            }

            public override fun matchesSafely(view: View): Boolean {

                this.resources = view.resources

                if (childView == null) {
                    val recyclerView = view.rootView.findViewById<RecyclerView>(recyclerViewId)
                    if (recyclerView?.id == recyclerViewId) {
                        val viewHolder = recyclerView.findViewHolderForAdapterPosition(position)
                        childView = viewHolder?.itemView
                    } else {
                        return false
                    }
                }

                return if (targetViewId == -1) {
                    view === childView
                } else {
                    val targetView = childView?.findViewById<View>(targetViewId)
                    view === targetView
                }
            }

        }
    }
}```


and the exception is here:


E/TestRunner: androidx.test.espresso.base.DefaultFailureHandler$AssertionFailedWithCauseError: 'with text: is "WE BRING"' doesn't match the selected view. Expected: with text: is "WE BRING" Got: "AppCompatTextView{id=2131231023, res-name=title, visibility=VISIBLE,...}"


Upvotes: 0

Views: 426

Answers (1)

Darwind
Darwind

Reputation: 7371

Converting my comment to an answer:

Try hardcoding the text inside the XML layout at first with WE BRING instead of relying on Databinding and see if that makes a difference.

There might be an issue with Databinding if you're not running executePendingBindings() after setting your datamodel on the XML layout.

Upvotes: 1

Related Questions