I have an abstract AccountRequiredActivity that looks like this (and works fine):
public abstract class AccountRequiredActivity extends LifecycleActivity {
@Inject
ViewModelProvider.Factory viewModelFactory;
private AccountViewModel accountViewModel;
public abstract void doOnCreate(Bundle savedInstanceState);
public abstract void doOnResume();
@Override
protected final void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_loading_app);
AndroidInjection.inject(this);
accountViewModel = ViewModelProviders.of(this, viewModelFactory).get(AccountViewModel.class);
if(!accountViewModel.isAuthenticated()) {
redirectToLogin();
} else {
doOnCreate(savedInstanceState);
};
}
@Override
protected void onResume() {
super.onResume();
if(!accountViewModel.isAuthenticated()) {
redirectToLogin();
} else {
doOnResume();
};
}
private void redirectToLogin() {
Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
}
}
The problem during tests is that there is no way for me to set the viewModelFactory
on the activity.
When an activity has a fragment, I can just do something like:
@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);
}
The problem however in this case is that I use this in my tests (HomeActivity extends AccountRequiredActivity):
@Rule
public ActivityTestRule<HomeActivity> activityTestRule = new ActivityTestRule<>(HomeActivity.class, true, false);
So there is no way to dynamically set the viewModelFactory
, as onCreate
immediately gets called. There doesn't seem to be a way to get access to the Activity object before onCreate
gets called.
How to fix this problem?
Note: I use Dagger 2.11 with AndroidInjector.
Also see this question that I posted yesterday for follow-up info:
Inject ViewModelFactory.Provider in activity for espresso testing
I solved the problem by overriding AndroidInjector's
inject()
method:Try to override dagger module for provide ViewModelProvider.Factory.
change testInstrumentationRunner 'com.eusecom.attendance.MockTestRunner' in app/build.gradle
call MockYourApplication.class in MockTestRunner
create new Mock dagger component in your MockYourApplication.class
before run testActivity override dagger component and module
Watch example https://github.com/eurosecom/Attendance/blob/master/app/src/androidTest/java/com/eusecom/attendance/DgAeaActivityTest.java
I have not used new dagger 2.11 with AndroidInjector ( i have used older dagger2 pattern ) but may be it helps.
you can create own testrule
and set as ActivityTestRule
in
beforeActivityLaunched()
you can then inject yourviewModelFactory
more here
It’s possible to set injected activity attribute by registering a custom ActivityLifecycleCallbacks in your TestApp in the @Before Method.
Example: