简体   繁体   中英

Injecting test module with dagger2

I use Dagger2 in my android app. Basically I inject a HttpClient (interface) in MainActivity .

@Module
public class MainActivityModule{

   @Provides public HttpClient providesHttpComponent(){
        return new RealHttpClient();
    }
}

@Component( modules = MainActivityModule.class )
public interface MainActivityComponent {
   public MainActivity injectActivity(MainActivity);
}



public class MainActivity extends Activity {

   public void onCreate(Bundle saved){
      super.onCreate();

      injectDependencies();
   }


   protected void injectDependencies(){

      Dagger_MainActivityComponent
        .builder()
        .mainActivityComponent( new MainActivityModule())
        .build()
        .injectActivity(this);
   }

}

So far so good, that works like expected. Now I want to write some unit tests (not android instrumentation tests) for MainActivity where I want to use TestMainActivityModule instead of MainActivityModule .

@Module (overrides = true )
public class TestMainActivtiyModule extends MainActivityModule {

   @Provides public HttpClient(){
      return new MockHttpClient();
   }

}

My question is: How do I force MainActivity to use TestMainActivitiyModule instead of MainActivityModule ? Is there a good solution for that?

My current approach is to use inheritance and to override getModule() , something like this

public class TestMainActivity extend MainActivity {

   @Override
   protected void injectDependencies(){

      Dagger_MainActivityComponent
        .builder()
        .mainActivityComponent( new TestMainActivtiyModule())
        .build()
        .injectActivity(this);
   }
}

and to run unit test against TestMainActivity instead of MainActivity .

I guess it works, but one of the problems I'm facing with this approach is that I can't start TestMainActivity with an Intent because I can't specify it in AndroidManifest.xml

Does anyone know a better approach for unit testing with dagger2 on android?

The approach I've started using has involved maintaining two modules (one for the app, one for testing) in parallel build variants (ex: app and integration ). Still not sure how well that solution scales so YMMV. I'd be very happy to see a better solution!

This is also a great read: http://engineering.circle.com/instrumentation-testing-with-dagger-mockito-and-espresso/

I would really suggest you to check this boilerplate since it is fully based on DI using Dagger2. It also shows how you can replace your dependencies in the test environment in a very neat way.

The dependencies currently handled by the boiler plate are the following:

  • Database dependency: encapsulates all the database operations.
  • Shared preferences dependency: deals with shared preferences.
  • Local files dependency: which deals with saving on files.
  • Analytics dependency: covers all the operation of reporting events to your analytics backend (GA, Segment, FB, Flurry ..)
  • Logging dependency: encapsulates all the operations related to logging to your console
  • Api dependency: encapsulates all the API related operations

The power of dependency injection comes really handy especially for testing since you can easily switch your dependencies in the test environment to dummy dependencies.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM