Mes
Mes

Reputation: 1691

Mock dependent component's dependency with DaggerMock

I want to write Espresso tests for an app so I'm trying DaggerMock to mock some external dependencies like local storage.

My Dagger setup consists of an ApplicationComponent with 3 modules (DatabaseModule, DataModule and ApplicationModule) and for the screen( a Fragment ) I want to test I have also another component which depends on ApplicationComponent.

What I have tried so far is :

@Rule public DaggerMockRule<ApplicationComponent> daggerRule =
        new DaggerMockRule<>(ApplicationComponent.class, new DatabaseModule(), new DataModule(application),
                new ApplicationModule(application)).set(
                component -> {
                    MyApplication app =
                            (MyApplication) InstrumentationRegistry.getInstrumentation()
                                    .getTargetContext()
                                    .getApplicationContext();
                    app.setComponent(component);
                });

@Rule
public final DaggerMockRule<FeedComponent> rule = new DaggerMockRule<>(
        FeedComponent.class, new FeedDataSourceModule(),
        new FeedDownloadImageUseCaseModule(), new FeedServiceModule(), new FeedPresenterModule(null))
        .addComponentDependency(ApplicationComponent.class, new DatabaseModule(), new DataModule(application), new ApplicationModule(application))
        .set(component -> localDataSource = component.localDataSource());

@Mock FeedDao feedDao;

@Mock NetworkUtils networkUtils;

@Mock FeedLocalDataSource localDataSource;

where localDataSource is actually the dependency I want to mock and it's build in FeedDataSourceModule :

@Module
public class FeedDataSourceModule {

@Provides
@FragmentScope
public FeedItemMapper providesFeedItemMapper() {
    return new FeedItemMapper();
}

@Provides
@FragmentScope
public FeedLocalDataSource providesFeedLocalDataSource(FeedDao feedDao, FeedRequestDetailsDao detailsDao, FeedItemMapper mapper) {
    return new FeedLocalDataSourceImpl(feedDao, detailsDao, mapper);
}

@Provides
@FragmentScope
public FeedRemoteDataSource providesFeedRemoteDataSource(FeedService feedService, FlagStateService flagStateService,
          @Named("Api-Token") String apiToken, @Named("Screen-Size") String screenSize,
                                                  @Named("Account-Id") String accountId) {
    return new FeedRemoteDataSourceImpl(feedService, flagStateService, apiToken, screenSize, accountId);
}

}

and also the FeedComponent with the dependency on ApplicationComponent :

@FragmentScope
@Component( dependencies = ApplicationComponent.class,
        modules = {
            FeedPresenterModule.class,
            FeedServiceModule.class,
            FeedDataSourceModule.class,
            FeedDownloadImageUseCaseModule.class})
public interface FeedComponent {

@Named("Api-Token") String getApiToken();

@Named("Api-Key") String getApiKey();

FeedLocalDataSource localDataSource();

FeedRemoteDataSource remoteDataSource();

void inject(FeedFragment feedFragment);
}

With the two @Rules I posted above I can confirm that NetworkUtils indeed seems to have been mocked correctly since I have used Mockito.when() to return false value and by using a breakpoint in my code I can see the value is always false :

    when(networkUtils.isOnline())
            .thenReturn(false);

But this is not true for localDataSource which gives me null when I'm calling localDataSource.getFeedSorted() although I have declared :

    when(localDataSource.getFeedSorted())
            .thenReturn(Flowable.just(feedList));

Just in case it helps, this is how I inject the dependencies from FeedComponent :

            DaggerFeedComponent.builder()
                .applicationComponent(MyApplication.getApplicationComponent())
                .feedPresenterModule(new FeedPresenterModule(this))
                .build()
                .inject(this);

Upvotes: 0

Views: 228

Answers (1)

Fabio Collini
Fabio Collini

Reputation: 474

Why are you using two DaggerMock rules in a test? I think you can use a single rule like in this example.

Upvotes: 1

Related Questions