I have a
Presenter
public class RssListPresenter {
@Inject
RssService rssService; // <-- injected field
public RssListPresenter() {
setupDI();
}
private void setupDI() {
DaggerNetworkComponent.builder()
.networkModule(new NetworkModule())
.build()
.inject(this);
}
public void loadItems() {
Rss rss = rssService.getRssFeed()
// ....
}
}
RssListPresenter
RssService
setRssService(RssService rssService)
@Singleton
@Component(modules = NetworkModule.class)
public interface NetworkComponent {
void inject(RssListPresenter presenter);
}
@Module
public class NetworkModule {
@Provides
Retrofit provideRetrofit() {
// ...
}
@Provides
@Singleton
RssService providePcWorldRssService(Retrofit retrofit) {
return retrofit.create(RssService.class);
}
}
Property injection is not amenable for testing. Constructor injection is much better. Refactor your constructor to look like this:
private final RssService rssService;
@Inject
public RssListPresenter(RssService rssService) {
this.rssService = rssService;
}
Now you can test it easily:
//mocks
RssService mockRssService;
//system under test
RssListPresenter rssListPresenter;
@Before
public void setup() {
mockRssService = Mockito.mock(RssService.class);
rssListPresenter = new RssListPresenter(mockRssService);
}
You shouldn't be using DaggerNetworkComponent.inject(this)
inside RssListPresenter
. Instead you should be configuring dagger so that when it injects members your top-level classes (Activity
, Fragment
, Service
) it can access the object graph and create an instance of your RssPresenter
.
To reiterate, Activity
, Fragment
etc. are valid injection targets. RssListPresenter
etc. are injected dependencies. You need to configure the dependency injection framework, dagger, so that it can provide the correct dependencies to inject into the injection targets.
So you will also need to write a @Provides
method for RssListPresenter
@Provides provideRssListPresenter(RssService rssService) {
return new RssListPresenteR(rssService);
}