使用 DaggerMock 模拟依赖组件的依赖

Mock dependent component's dependency with DaggerMock

我想为应用程序编写 Espresso 测试,所以我正在尝试 DaggerMock 模拟一些外部依赖项,如本地存储。

我的 Dagger 设置包含一个 ApplicationComponent 和 3 个模块(DatabaseModule、DataModule 和 ApplicationModule)和屏幕(一个 Fragment )我想测试我还有另一个依赖于 ApplicationComponent 的组件。

到目前为止我尝试过的是:

@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;

其中 localDataSource 实际上是我想要模拟的依赖项,它是在 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);
}

}

还有 FeedComponent 依赖于 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);
}

通过我在上面发布的两个 @Rules,我可以确认 NetworkUtils 确实似乎被正确地嘲笑了,因为我使用了 Mockito.when() 到 return false 值,通过在我的代码中使用断点,我可以看到该值始终为 false :

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

但这对 localDataSource 来说并非如此,虽然我已经声明:

,但当我调用 localDataSource.getFeedSorted() 时它会给我 null
    when(localDataSource.getFeedSorted())
            .thenReturn(Flowable.just(feedList));

为了以防万一,这就是我从 FeedComponent 注入依赖项的方式:

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

为什么要在测试中使用两个 DaggerMock 规则?我认为您可以使用 example.

中的单个规则