androidjunit4android-espressodagger-hiltinstrumented-test

NoMatchingViewException error during Espresso test


I am doing an instrumentation test of Fragment is displayed or not. When I start the test it execute, I am able to see FragmentLogin view in physical device but test fail by saying androidx.test.espresso.NoMatchingViewException: No views in hierarchy found matching: view.getId() is <2131296460/com.nano.modularapp:id/fragmentLogin> and app close.

I used Hilt and Navigation Graph in my code for testing.

FragmentLogin.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="login"
            type="com.nano.modularapp.login.FragmentLogin" />

    </data>
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".login.FragmentLogin">

        <TextView
            android:id="@+id/tvSignUpTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Welcome in ModularApp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            android:layout_marginTop="20dp"
            android:layout_marginStart="20dp"
            android:textColor="@color/black"
            android:fontFamily="@font/mukta_bold"
            android:textSize="26sp"
            android:textStyle="bold"/>


        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toBottomOf="@id/tvSignUpTitle"
            app:layout_constraintStart_toStartOf="parent"
            android:text="Login"
            android:textColor="@color/black"
            android:layout_marginTop="20dp"
            android:layout_marginStart="20dp"
            android:fontFamily="@font/mukta_medium"
            android:textSize="22sp" />

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            android:layout_margin="20dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Email"
            android:textSize="20sp"
            android:layout_marginTop="15dp"
            android:textColor="@color/text_color"
            android:fontFamily="@font/mukta_medium"/>

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/editTextEmail"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Email"
            android:layout_marginTop="5dp"
            android:textColor="@color/text_color"
            android:fontFamily="@font/mukta_regular"
            android:textSize="18sp"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Password"
            android:textSize="20sp"
            android:layout_marginTop="20dp"
            android:textColor="@color/text_color"
            android:fontFamily="@font/mukta_medium"
            android:inputType="textEmailAddress"/>

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/editTextPassword"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Password"
            android:layout_marginTop="5dp"
            android:textColor="@color/text_color"
            android:fontFamily="@font/mukta_regular"
            android:textSize="18sp"
            android:inputType="textPassword"/>

        <TextView
            android:id="@+id/tvError"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="15sp"
            android:layout_marginTop="15dp"
            android:fontFamily="@font/mukta_regular"
            android:text="@{login.errorMsg}"
            android:textColor="@color/error"/>

        <Button
            android:id="@+id/btnLogin"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Login"
            android:textSize="20sp"
            android:paddingStart="20dp"
            android:paddingEnd="20dp"
            android:layout_marginTop="25dp"
            android:layout_gravity="center"
            android:fontFamily="@font/mukta_semi_bold"/>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:padding="8dp"
                android:gravity="center">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="15sp"
                    android:text="Don't have an account?"
                    android:textColor="@color/black"
                    android:fontFamily="@font/mukta_regular"/>

                <TextView
                    android:id="@+id/navigateToSignUp"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="18sp"
                    android:text="  Sign Up"
                    android:textColor="@color/info_blue"
                    android:fontFamily="@font/mukta_medium"/>

            </LinearLayout>

        </LinearLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

FragmentLoginInstrumentedTest::class

@HiltAndroidTest
@RunWith(AndroidJUnit4::class)
class FragmentLoginInstrumentedTest {

    @get:Rule
    val hiltRule:HiltAndroidRule = HiltAndroidRule(this)

    @get:Rule
    val activityRule: ActivityScenarioRule<HiltTestActivity> = ActivityScenarioRule(HiltTestActivity::class.java)

    @Before
    fun init(){
        hiltRule.inject()
    }

    @Test
    fun test_blankField_expectedEmptyField(){
        //Checking LoginFragment is attached and displayed in screen or not
        launchFragmentInHiltContainer<FragmentLogin>()
onView(withId(R.id.fragmentLogin)).check(ViewAssertions.matches(isDisplayed()))

}

Above is my complete code. I don't understand the reason, login fragment display and then test case fail.


Solution

  • I am able to solve this issue. A very small point need to look here

    When you are using Hilt + Navigation for loading your fragments using NavController. During android instrumentation test few points need to consider

    1. When running instrumentation test annotate @RunwWith(AndroidJUnitRunner::class)

    2. Set another rule on which activity you will launch Fragment. As you are using fragment you need to create HiltTestActivity in debug main folder inside java directory.

    3. List While writing Espresso.onView(withId(R.id.loginFragment)) --> replace it with Espresso.onView(withId(R.id.loginFragmentView)). "loginFragmentView" you need to add it in your root view of fragment layout file name.

    for your reference look into this github solution NoMatchingViewException issue