JFYI : overriding @Module classes with Dagger 2 [in tests]

You can override @Module class, for example for tests.

But annotations on overridden @Provides methods eg @Singleton, @Named, etc won't override original ones because Dagger 2 generates code for initial @Module + @Component classes (for @Module mentioned in @Component(modules = …).

Yes, you can pass overridden implementations when you build an instance of @Component but it won't affect generated code.

Example, main code

@Module
public class SomeModule {

  @Provides @NonNull @Named("very_special_thing") @Singleton
  public SomeThing provideSomeThing(@NonNull SomeArgs someArgs) {
    return new SomeThing(someArgs);
  }
}

@Component(modules = SomeModule.class)
public interface SomeComponent {  
  void inject(@NonNull TargetClass target);
}

In tests

// No need for @Module annotation
public class SomeModuleForTest extends SomeModule {

  // No need for DI annotations here.
  // Even if you put annotations like @Named, @Singleton, etc 
  // they won't affect generated code so you can't override this behavior of original @Module class.
  @Override
  public SomeThing provideSomeThing(@NonNull SomeArgs someArgs) {
    return mock(SomeThing.class);
  }
}

Then you can pass overridden module:

SomeComponent someComponent = new DaggerSomeComponent.Builder()  
  .someModule(new SomeModuleForTest())
  .build();

That's it. Mostly it does not matter since you want same behavior in TestModule as the original @Module, but JFYI ¯_(ツ)_/¯.

Moreover, looks like it's not possible to support such feature easily because actually, scoping annotations affect code generated for a @Component, not the @Module.

https://twitter.com/artem_zin

comments powered by Disqus