我已经尝试了一个星期。而且,我已经检索了所有可用的文章,但它们的实现或示例不完善或在Espresso Tests的步骤中停了下来。
我的Android应用程序遵循MVP架构(并且使用Java)
场景:[仅举一个例子]
我有一个HomeActivity
,使用Dagger2得到了HomePresenter
。 (在HomeModule
中通过void inject(HomeActivity activity)
的{{1}}公开的HomeComponent
中提供方法。
在我的HomeActivity
的espressoTest中,我想注入一个模拟礼物。
我尚未通过AppModule
在AppComponent
内部公开此依赖性。网上的大多数示例都这样做(因此,他们只是创建了一个新的testApplication,然后执行Needfull)
我不想使用productFlavours方式注入或提供模拟类,因为它无法控制Mockito.when
方法。
基本上。我想注入一个模拟演示者,为了对espresso进行单元测试,我可以在其中执行任何Mockito.when()
操作。
HomeComponent
@HomeScope
@Component(modules = HomeModule.class,dependencies = AppComponent.class)
public interface HomeComponent {
void inject(HomeActivity activity);
}
HomeModule
@Module
public class HomeModule {
private final IHomeContract.View view;
public HomeModule(IHomeContract.View view) {
this.view = view;
}
@Provides
@HomeScope
public IHomeContract.Presenter presenter(FlowsRepository flowsRepository, UserRepository userRepository, LoanRepository loanRepository) {
return new HomePresenter(view, flowsRepository, userRepository, loanRepository);
}
}
AppComponent
@Component(modules = {AppModule.class,RepositoryModule.class})
@AppScope
public interface AppComponent {
void inject(App app);
FlowsRepository flowRepository();
LoanRepository loanRepository();
UserRepository userRepository();
}
AppModule
@Module
public class AppModule {
private Context appContext;
public AppModule(@NonNull Context context) {
this.appContext = context;
}
@Provides
@AppScope
public Context context() {
return appContext;
}
}
应用
component = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();
component.inject(this);
家庭活动
HomeComponent component = DaggerHomeComponent.builder()
.appComponent(((App) getApplication()).getComponent())
.homeModule(new HomeModule(this))
.build();
再次。在我的测试(浓缩咖啡)中,我想注入Mockito的嘲笑的HomePresenter。这样我就可以对我的观点进行单元测试。
答案 0 :(得分:7)
解决该问题的关键是要有一个 Dagger模块,它可以在HomeActivity
的测试中提供模拟的 Presenter ,而不是“真实”。
为此,需要完成以下两个额外的操作(您可能还希望看到一个example )。
在下面的示例中,我将使用 Kotlin 。
定义委托接口:
interface HomeComponentBuilder {
fun build(view: IHomeContract.View): HomeComponent
}
将HomeComponent
的初始化从HomeActivity
移至委托实现:
class HomeComponentBuilderImpl constructor(private val app: App) : HomeComponentBuilder {
override fun build(view: IHomeContract.View): HomeComponent =
DaggerHomeComponent.builder()
.homeModule(HomeModule(view))
.build()
}
使委托处于应用程序“作用域”中,以便您可以将其实现互换用于仪器测试:
interface App {
val homeComponentBuilder: HomeComponentBuilder
...
}
App
实现现在应包含
class AppImpl : Application(), App {
override val homeComponentBuilder: HomeComponentBuilder by lazy {
HomeComponentBuilderImpl(this@AppImpl)
}
...
}
HomeActivity
中的组件初始化如下:
(application as App)
.homeComponentBuilder
.build(this)
.inject(this)
对于仪器化测试,请创建扩展TestHomeComponent
的{{1}}:
HomeComponent
其中@HomeScope
@Component(modules = [TestHomeModule::class])
interface TestHomeComponent : HomeComponent
提供了一个模拟 Presenter
TestHomeModule
剩下要做的就是制作一个测试委托实现
@Module
class TestHomeModule {
@Provides
fun providePresenter(): IHomeContract.Presenter = mock()
}
并在class TestHomeComponentBuilderImpl : HomeComponentBuilder {
override fun build(view: IHomeContract.View): HomeComponent =
DaggerTestHomeComponent.builder()
.testTestHomeModule(TestHomeModule())
.build()
}
TestAppImpl
其余均为标准配置。创建使用class TestAppImpl : Application(), App {
override val homeComponentBuilder: HomeComponentBuilder by lazy {
TestHomeComponentBuilderImpl()
}
...
}
的自定义AndroidJUnitRunner
:
TestAppImpl
并将其添加到class TestAppRunner : AndroidJUnitRunner() {
override fun newApplication(cl: ClassLoader?, className: String?, context: Context?): Application = Instrumentation.newApplication(TestAppImpl::class.java, context)
}
模块app
build.gradle
用法示例:
defaultConfig {
testInstrumentationRunner "your.package.TestAppRunner"
...
}
答案 1 :(得分:0)
所以。您的问题是您需要创建一个模块,该模块提供用于测试的模拟演示者,而不是“真实的”演示者。
这里有一篇很好的文章:Testing with Dagger