Well, first, user2511882 I tried your solution before posting the question, but the fact is that if you look at the TestMyApplication structure, where I insert the test module, you will see that your proposal and my previous attempts cannot work.
After rethinking the whole problem, I found a solution in accordance with my initial attempts, as well as a more useful solution (as far as I can see). First, I no longer rely on the TestMyApplication class. In addition, I had to make some changes to the MyApplication class to make it more "test-friendly" (without changing its functionality). Therefore, the MyApplication class is as follows:
public class MyApplication extends DaggerApplication { private List<Object> modules; public MyApplication() { modules = new ArrayList<Object>(); modules.add(new AppModule(this)); } @Override protected List<Object> getAppModules() { return modules; } }
Now I can create two test modules in which I set the behavior to return true when requesting an Internet connection, and one that returns false for the same request.
Now in my test class I will have the following:
@RunWith(RobolectricTestRunner.class) public class SplashScreenActivityTest { SplashScreenActivity activity; public void setUpNoInternet() { // Now I can add the new test module to the application modules to override the real one in the application onCreate() method ((MyApplication)Robolectric.application).getAppModules().add(new GeneralUtilsModuleNoInternetConnection()); activity = Robolectric.buildActivity(SplashScreenActivity.class).create().get(); } public void setUpWithInternet() { ((MyApplication)Robolectric.application).getAppModules().add(new GeneralUtilsModuleWithInternetConnection()); activity = Robolectric.buildActivity(SplashScreenActivity.class).create().get(); } @Test public void testOnCreate_whenNoInternetConnection() { setUpNoInternet(); } @Test public void testOnCreate_whenThereIsInternetConnection() { setUpWithInternet(); } }
This works great and fits my initial test plan. But I think there is a more elegant solution instead of creating a new test module for each situation. The modified test module is as follows:
@Module( includes = AppModule.class, injects = {SplashScreenActivityTest.class, SplashScreenActivity.class}, overrides = true ) public class GeneralUtilsModuleTest { private GeneralUtils mockGeneralUtils; public GeneralUtilsModuleTest() { mockGeneralUtils = Mockito.mock(GeneralUtils.class); } @Provides @Singleton GeneralUtils provideGeneralUtils() { return mockGeneralUtils; } public GeneralUtils getGeneralUtils() { return mockGeneralUtils; } public void setGeneralUtils(final GeneralUtils generalUtils) { this.mockGeneralUtils = generalUtils; } }
Using this, the Test class looks like this:
@RunWith(RobolectricTestRunner.class) public class SplashScreenActivityTest { SplashScreenActivity activity; private GeneralUtilsModuleTest testModule; private GeneralUtils generalUtils; @Before public void setUp() { testModule = new GeneralUtilsModuleTest(); generalUtils = Mockito.mock(GeneralUtils.class); } public void setUpNoInternet() { when(generalUtils.isInternetConnection()).thenReturn(false); testModule.setGeneralUtils(generalUtils); ((MyApplication)Robolectric.application).getAppModules().add(testModule); activity = Robolectric.buildActivity(SplashScreenActivity.class).create().get(); } public void setUpWithInternet() { when(generalUtils.isInternetConnection()).thenReturn(true); testModule.setGeneralUtils(generalUtils); (MyApplication)Robolectric.application).getAppModules().add(testModule); activity = Robolectric.buildActivity(SplashScreenActivity.class).create().get(); } .....(Tests).... }
Thanks to everyone for your help, and I really hope that this solution will help others achieve better testing on Android.