Home » Android » android – Unit tests NPE, when I add fragment custom transitions

android – Unit tests NPE, when I add fragment custom transitions

Posted by: admin May 14, 2020 Leave a comment

Questions:

OnBackPressed() test throws NPE when I added a custom transitions. It’s fine without the custom transitions. Why?

THIS NPE ONLY HAPPENS IN UNIT TEST, NOT THE APP.

 class MyActivity {
    @Override
    public void onBackPressed() {
        .......
        super.onBackPressed();
    }

    private void putFragment(Fragment fragment) {
            String tag = fragment.getClass().getName();

            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

            // TEST FAILED IF I ADD THE FOLLOWING LINE
            transaction.setCustomAnimations(
                    R.anim.slide_in_left_fade_in,
                    R.anim.fade_out_short_anim_time,
                    R.anim.fade_in_short_anim_time,
                    R.anim.slide_out_right_fade_out);

            transaction.replace(R.id.ub__add_profiles_content, fragment, tag);
            transaction.addToBackStack(tag);
            transaction.commit();
    }
}

class MyActivityTest extends RiderRobolectricBase {

    @Test
    public void onBackPressed() {
       putFragment(someFragment);

       mMyActivity.onBackPressed();
    }
}

Exception:

java.lang.NullPointerException
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1126)
    at android.support.v4.app.FragmentManagerImpl.removeFragment(FragmentManager.java:1304)
    at android.support.v4.app.BackStackRecord.popFromBackStack(BackStackRecord.java:909)
    at android.support.v4.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1625)
    at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:561)
    at android.support.v4.app.FragmentActivity.onBackPressed(FragmentActivity.java:166)
    at MyActivity.onBackPressed(MyActivity.java:28)
How to&Answers:

Onbackpress you are reversing the previous steps from within the backstack. The first is to
remove the existing fragment. The fragment is detached from the activity and
you are not retaining an instance of this fragment.

java.lang.NullPointerException
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1126)
    at android.support.v4.app.FragmentManagerImpl.removeFragment(FragmentManager.java:1304)
    at android.support.v4.app.BackStackRecord.popFromBackStack(BackStackRecord.java:909)
    at android.support.v4.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1625)
    at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:561)
    at android.support.v4.app.FragmentActivity.onBackPressed(FragmentActivity.java:166)
    at MyActivity.onBackPressed(MyActivity.java:28)

You the call putFragment(someFragment).
So when you go to call setCustomAnimations. The previous view is not saved to be used in the transition.

// TEST FAILED IF I ADD THE FOLLOWING LINE
transaction.setCustomAnimations(
    R.anim.slide_in_left_fade_in,
    R.anim.fade_out_short_anim_time,
    R.anim.fade_in_short_anim_time,
    R.anim.slide_out_right_fade_out);

You can retain the instance in your oncreate method of your fragment:

setRetainInstance(true);

As for this working in your app, I cannot see the code within your onBackPressed event of your Activity.

Answer:

The code seems correct. I suspect you cannot call addToBackStack() after using replace() due to setCustomAnimations call. So for a quick test, simply remove the call to addToBackStack.

Normally you can call addToBackStack() after replace(). I do it many times.

Let me know of your results…