Search code examples
androidjunitmockitodagger-2daggermock

DaggerMock - How to get dagger to provide object in a test case


I am doing a junit testing on a use case i have (MVP architecture if that matters) with dagger2. The problem is i would like to use Dagger2 injection inside of my junit test case sometimes. So i looked into DaggerMock library for this. I have a certain dependency i would like built for me but it keeps returning null. Let me show you how i set up dagger first.

its a single component (tried subcomponents but daggerMock was not happy with it): AppComponent.java:

@Singleton
@Component(modules = {AppModule.class, NetworkModule.class, RepositoryModule.class, UseCaseModule.class, ActivityModule.class, PresenterModule.class})
public interface AppComponent {
    void inject(NetworkSessionManager target);
    void inject(SplashActivity target);
    void inject(AuthenticationActivity target);
    void inject(WelcomeActivity target);
    void inject(LoginFragment target);
}

The rest of the classes are annotated with @inject. if you annotate with @Inject the class constructor all it means is you dont have to delcare it in the AppComponent interface above.

So here is my test case with DaggerMock:

    @Rule
   public final DaggerMockRule<AppComponent> rule = new DaggerMockRule<>(AppComponent.class, new AppModule(null),new RepositoryModule(),new NetworkModule(),new UseCaseModule());


    StandardLoginInfo fakeLoginInfo;
    TestObserver<Login> subscriber;

    DoStandardLoginUsecase target_standardLoginUsecase;//this is what im trying to test so its real

    @InjectFromComponent
    UserDataRepository userDataRepository; //id like this to be a real instance also but it keeps showing as null 

    @Before
    public void setUp() throws Exception {

        target_standardLoginUsecase = new DoStandardLoginUsecase(userDataRepository); // this gets passed a null, why ?
        subscriber = TestObserver.create();
    }

//....

}

if we look at the rule i defined i included all my modules from the appcomponent so i was thinking that i have all dependencies available to me. I passed in null to the AppModule as its expected a context, i dont think its a big deal.

I though the @InjectFromComponent annotation would give me what i wanted. i even tried @InjectFromComponent(DoStandardLoginUsecase.class) but that does not work. I want it to go into the AppComponent android build me a UserDataRepository object. Since i am using all the modules in DaggreMockRule i thought it would not have a hard time to do this ?

How can i get dagger2 to build me a real object ?


Solution

  • The trick here is that whatever you want to inject has to be directly exposed in the component. So for example have your component like this:

    @Singleton
    @Component(modules = {AppModule.class, TestNetworkModule.class, RepositoryModule.class, ActivityModule.class})
    public interface TestAppComponent {
    
        void inject(LoginFragment target);
        void inject(SignUpFragment target);
    
        MockWebServer server();
        UserDataRepository userDataRepo(); //these two can be injected because they are directly exposed (still put them in your module as usual. this just directly exposes them so daggermock can use them)
    }