I am trying to write an Android application using Dagger. Trying to follow the TDD approach, I started writing a test for my First activity. For writing tests I am using Robole
Ok, first off, user2511882 I have tried your solution before posting the question but the thing is, if you look at the structure of TestMyApplication, where I inject the test module, you would see that your suggestion and my previous tries could not work.
After rethinking the whole problem I have found a solution along the lines of my initial tries and also a more useful solution (as far as I can see it). First off, I do not rely on the TestMyApplication class anymore. Furthermore I had to do some changes to MyApplication class to make it more "test friendly" (without changing its functionality). So MyApplication class looks like this:
public class MyApplication extends DaggerApplication
{
private List
Now I can create the two test modules, one in which I set the behavior to return true when asking for an internet connection and one which will return false for the same query.
Now, in my test class I would 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 fine and is along the lines of my initial plan of testing. But I think there is a more elegant solution instead of creating a new test module for each situation. The modified test module looks like this:
@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)....
}
Thank you all for your help and I really hope that this solution will help others achieve better testing on Android.