使用 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.
中的单个规则
我想为应用程序编写 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.
中的单个规则