Espresso, Dagger2 set ViemodelProvider.Factory on BaseActivity

后端 未结 4 1642
[愿得一人]
[愿得一人] 2021-01-11 09:19

I have an abstract AccountRequiredActivity that looks like this (and works fine):

public abstract class AccountRequiredActivity extends LifecycleActivity {
         


        
相关标签:
4条回答
  • 2021-01-11 10:06

    I solved the problem by overriding AndroidInjector's inject() method:

    @Override
    public AndroidInjector<Activity> activityInjector() {
        return new AndroidInjector<Activity>() {
            @Override
            public void inject(Activity instance) {
                AccountViewModel viewModel = mock( AccountViewModel.class );
                if(instance instanceof TestHomeActivity) {
                    ((TestHomeActivity) instance).viewModelFactory = ViewModelUtil.createFor( viewModel );
                }
            }
        };
    } 
    
    0 讨论(0)
  • 2021-01-11 10:16

    It’s possible to set injected activity attribute by registering a custom ActivityLifecycleCallbacks in your TestApp in the @Before Method.

    Example:

     @Before
    public void init(){
    
    UserFragment fragment = UserFragment.create("foo");
    viewModel = mock(UserViewModel.class);
    when(viewModel.getUser()).thenReturn(userData);
    when(viewModel.getRepositories()).thenReturn(repoListData);
    navigationController = mock(NavigationController.class);
    
    
    TestApp testApp = ((TestApp) InstrumentationRegistry.getContext().getApplicationContext());
    testApp.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            //will be called before the onCreate method of your activity
            activity.setViewModelFactory(ViewModelUtil.createFor(viewModel));
        }
    
        @Override
        public void onActivityStarted(Activity activity) {
    
        }
    
        @Override
        public void onActivityResumed(Activity activity) {
    
        }
    
        @Override
        public void onActivityPaused(Activity activity) {
    
        }
    
        @Override
        public void onActivityStopped(Activity activity) {
    
        }
    
        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    
        }
    
        @Override
        public void onActivityDestroyed(Activity activity) {
    
        }
    });
    
    
    fragment.viewModelFactory = ViewModelUtil.createFor(viewModel);
    fragment.navigationController = navigationController;
    fragment.dataBindingComponent = () -> fragmentBindingAdapters;
    
    activityRule.getActivity().setFragment(fragment);
    
    
    }
    
    0 讨论(0)
  • 2021-01-11 10:21

    you can create own testrule

    public class MyCustomRule<A extends MainActivity> extends ActivityTestRule<A> {
        public MyCustomRule(Class<A> activityClass) {
            super(activityClass);
        }
    
        @Override
        protected void beforeActivityLaunched() {
            super.beforeActivityLaunched();
            // Maybe prepare some mock service calls
            // Maybe override some depency injection modules with mocks
        }
    
        @Override
        protected Intent getActivityIntent() {
            Intent customIntent = new Intent();
            // add some custom extras and stuff
            return customIntent;
        }
    
        @Override
        protected void afterActivityLaunched() {
            super.afterActivityLaunched();
            // maybe you want to do something here 
        }
    
        @Override
        protected void afterActivityFinished() {
            super.afterActivityFinished();
            // Clean up mocks
        }
    }
    

    and set as ActivityTestRule

    @Rule
    public ActivityTestRule<MainActivity> testRule = new MyCustomRule<>(MainActivity.class);
    

    in beforeActivityLaunched() you can then inject your viewModelFactory

    more here

    0 讨论(0)
  • 2021-01-11 10:24

    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.

    0 讨论(0)
提交回复
热议问题