Overriding the debug module in tests

I have a Gradle application with a project structure similar to Jake Wharton u2020 :

/src /androidTest /debug /main /release 

In my application class, I create a dagger graph and insert it:

 MyApplication extends Application { ... public void buildObjectGraphAndInject() { Object[] modules = Modules.list(this); mApplicationGraph = ObjectGraph.create(modules); mApplicationGraph.inject(this); } ... } 

Inside a set of debugging options, I define Modules.list() as:

 public final class Modules { public static Object[] list(MyApplication app) { return new Object[] { new AppModule(app), new DebugAppModule() }; } private Modules() { // No instances. } } 

Inside the release release set, I define the same minus DebugAppModule:

 public final class Modules { public static Object[] list(MyApplication app) { return new Object[] { new AppModule(app) }; } private Modules() { // No instances. } } 

A deeper dependency graph, I create a MockRestAdapter, which I can use when starting the debug version:

 @Module( complete = false, library = true, overrides = true ) public final class DebugApiModule { @Provides @Singleton Endpoint provideEndpoint(@ApiEndpoint StringPreference apiEndpoint) { return Endpoints.newFixedEndpoint(apiEndpoint.get()); } @Provides @Singleton MockRestAdapter provideMockRestAdapter(RestAdapter restAdapter, SharedPreferences preferences) { MockRestAdapter mockRestAdapter = MockRestAdapter.from(restAdapter); AndroidMockValuePersistence.install(mockRestAdapter, preferences); return mockRestAdapter; } @Provides @Singleton MyApi provideMyApi(RestAdapter restAdapter, MockRestAdapter mockRestAdapter, @IsMockMode boolean isMockMode, MockMyApi mockService) { if (isMockMode) { return mockRestAdapter.create(MyApi.class, mockService); } return restAdapter.create(MyApi.class); } } 

But while I run the tests, I would like to override DebugApiModule with TestApiModule, which looks like this:

 @Module( complete = false, library = true, overrides = true ) public final class TestApiModule { @Provides @Singleton Endpoint provideEndpoint(@ApiEndpoint StringPreference apiEndpoint) { return Endpoints.newFixedEndpoint(apiEndpoint.get()); } @Provides @Singleton MockRestAdapter provideMockRestAdapter(RestAdapter restAdapter, SharedPreferences preferences) { MockRestAdapter mockRestAdapter = MockRestAdapter.from(restAdapter); mockRestAdapter.setDelay(0); mockRestAdapter.setErrorPercentage(0); mockRestAdapter.setVariancePercentage(0); return mockRestAdapter; } @Provides @Singleton MyApi provideMyApi(MockRestAdapter mockRestAdapter, MockHnApi mockService) { return mockRestAdapter.create(MyApi.class, mockService); } } 

What is the best way to achieve this? I need to create a TestAppModule as follows:

 public final class Modules { public static Object[] list(MyApplication app) { return new Object[] { new AppModule(app), new TestAppModule() }; } private Modules() { // No instances. } } 

And replace all DebugFooModule with TestFooModules ? If so, how do I get around the fact that Modules.java duplicated? Or am I out of base?

EDIT: SOLUTION

What I ended up with is replacing the application level graph (where the MockRestAdapter is created) during my setUp test

 protected void setUp() throws Exception { super.setUp(); HnApp app = HnApp.getInstance(); app.buildObjectGraphAndInject(TestModules.list(app)); getActivity(); } 
+3
android dagger
Aug 12 '14 at 18:39
source share
1 answer

What I have done so far (and I'm not quite sure that this is not scalable yet) creates in my tests a static test module class.

  @Module( injects = { SharedPreferences.class }) static class TestModule { @Provides @Singleton SharedPreferences provideSharedPreferences(){ return Mockito.mock(SharedPreferences.class); } } 

And in the setup () method, I insert a test module

  @Before public void setUp(){ ObjectGraph.create(new TestModule()).inject(this); } 

Then I insert the mocked class:

 @Inject SharedPreferences sharedPreferences; 
+1
Aug 18 '14 at 18:10
source share



All Articles