samedi 23 septembre 2017

Android instrumentation test a fragment: Cast fake Activity to specific LoginActivity

I have an annoying dilemma related to my instrumentation test.

The code under test is in LoginFragment:

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    loginActivity = (LoginActivity) getActivity();
    accountViewModel = ViewModelProviders.of(this, viewModelFactory).get(AccountViewModel.class);
    accountViewModel.getAuthenticatedUserResource().observe(this, authenticatedUserResource -> {
        binding.get().setAuthenticatedUserResource( authenticatedUserResource );
        binding.get().executePendingBindings();

        if(authenticatedUserResource.status == Status.SUCCESS) {
            loginActivity
                    .redirectToHome();
        }
    });
}

My test specifies:

@RunWith(AndroidJUnit4.class)
public class LoginFragmentTest {
    private static final String fbId = "xxxxxx";
    private static final String fbUsername = "xxxxxx";
    private static final String genderShort = "m";
    private static final String lfId = "xxxxxxxxxx";
    private static final String jwt = "xxxxxxxxx";
    private static final String refreshToken = "xxxxxxxx";

    @Rule
    public ActivityTestRule<LoginFragmentActivity> activityRule =
            new ActivityTestRule<>(LoginFragmentActivity.class, true, true); <-- LoginFragmentActivity is a fake replacement for LoginActivity

    private AccountViewModel viewModel;
    private MutableLiveData<Resource<AuthenticatedUser>> authenticatedUser = new MutableLiveData<>();

    @Before
    public void init() {
        LoginFragment fragment = LoginFragment.newInstance();
        viewModel = mock(AccountViewModel.class);
        when(viewModel.getAuthenticatedUserResource()).thenReturn(authenticatedUser);

        fragment.viewModelFactory = ViewModelUtil.createFor(viewModel);
        activityRule.getActivity().setFragment(fragment); <-- set the fragment under test
    }

    @Test
    public void loginSuccess() {
        User user = new User(lfId, fbId, fbUsername, genderShort);
        AuthenticatedUser authUser = new AuthenticatedUser(user, jwt, refreshToken);
        authenticatedUser.postValue(Resource.success(authUser));
        intended(toPackage("com.example.kimgysen.livefeed_v002.ui.home.HomeActivity"));
    }

I use LoginFragmentActivityas a fake replacement for the actual activity (being LoginActivity).
The test is taken from the example provided by: http://ift.tt/2wO2aHl

The problem is in my actual Activity, I try to make a cast (repetition of previous code with indication of the concerning line), which fails because I use a fake LoginFragmentActivity:

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    loginActivity = (LoginActivity) getActivity(); // <--- This line
    accountViewModel = ViewModelProviders.of(this, viewModelFactory).get(AccountViewModel.class);
    accountViewModel.getAuthenticatedUserResource().observe(this, authenticatedUserResource -> {
        binding.get().setAuthenticatedUserResource( authenticatedUserResource );
        binding.get().executePendingBindings();

        if(authenticatedUserResource.status == Status.SUCCESS) {
            loginActivity
                    .redirectToHome(); <-- In order to execute this line
        }
    });
}

The functionality works when testing manually on the device. Let me know if not clear.

Aucun commentaire:

Enregistrer un commentaire