0

recently I worked on Android projects with data binding. When I try to create a fragment unit test, it says that the data binding is null.

Here is the code exception trace :

java.lang.NullPointerException: Attempt to read from field 'android.support.design.widget.TextInputLayout com.example.android.databinding.AFragmentBinding.textInputMortgagePrice' on a null object reference

Here's my unit test code snippet :

public void testIsInputValid() {
    assertTrue(mFragment.isInputValid());
}

And here is my AFragment.java code snippet :

public class AFragment {
    private AFragmentBinding binding;

    @Override
    public boolean isInputValid() {
        resetError();
        return !isEmptyEditTextExist(); //A method to check if the text is empty
    }

    private void resetError() {
        binding.aTextInput.setError(null); //Here's where the error found
    }
}

Here is my fragment.xml :

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

<data>

    <variable
        name="vmA"
        type="path.to.viewmodel.class"/>
</data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
            <android.support.design.widget.TextInputLayout
                android:id="@+id/a_text_input"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <EditText
                    android:id="@+id/a_edit_text"
                    android:imeOptions="actionNext"
                    android:inputType="number"
                    android:maxLength="17"
                    android:text="@={vmA.price}"/>

                </android.support.design.widget.TextInputLayout>
</LinearLayout>

Does anybody know how to test a fragment / activity with data binding? Thanks for your help.

1 Answers1

0

It looks I find the answer myself. The problem is not the data binding, but the test itself. When I test the isInputValid() method, I need to start the fragment first in the setUp() method. Here's some references how to start a fragment in unit test (the second answer).

Or if you're not going to set it up first, you can just edit the testIsInputValid, like this :

public void testIsInputValid() {
    FragmentManager fragmentManager = mActivity.getSupportFragmentManager();
    FragmentTransaction ft = fragmentManager.beginTransaction();
    ft.add(mFragment, null);
    ft.commit();
    getActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
            getActivity().getSupportFragmentManager().executePendingTransactions();
        }
    });
    getInstrumentation().waitForIdleSync();
    assertTrue(mFragment.isInputValid());
}

EDIT : The second option is actually a bad practice because you need to repeat the code over and over again. So, I recommend you to write the code in setUp() method