【发布时间】:2021-04-14 15:06:43
【问题描述】:
我计划在我的应用程序多模块上创建 Espresso 测试,我即将创建第一个 Espresso 测试,但我看到的是在我的应用程序上我没有 AppComponent 在哪里我可以伪造它。由于我想在我的功能模块上添加测试,我将从现在开始在那里创建TestApp、TestRunner。
我的功能模块上有一个FeatureComponent,它是通过ComponentFactory 从App 注入的,所以我想创建一个这样的类:
@Component (
dependencies = [ MoreComponents::class],
modules = [ DataSourceModule::class ]
)
interface FeatureOneComponent {
fun activityOneSubComponent(): FeatureOneActivity.Component.Factory
fun activityTwoSubComponent(): FeatureTwoActivity.Component.Factory
@Component.Factory
interface Factory {
fun create(
dependencies
):FeatureOneComponent
}
}
interface FeatureOneProvider {
fun getFeatureOneComponent(): FeatureOneComponent
}
///ACTIVITY
class FeatureOneActivity : AppCompatActivity() {
//this comes from Subcomponent is what I want to MOCK
@Inject lateinit var presenter
//these comes from the factory and I have it mocked
@Inject lateinit var manager
override fun onCreate(){
(applicationContext as FeatureOneProvider).getFeatureOneComponent().activityOneSubComponent().create(this).inject(this)
}
}
@Subcomponent(modules = [ActivityOneModule::class]) <--- THIS I WANT TO MOCK
interface Component {
fun inject(activity: FeatureOneActivity)
@SubComponent.Factory
interface Factory {
fun create(@BindsInstance activity: FeatureOneActivity): Component
}
}
@Module
interface ActivityOneModule {
@Binds
fun bindPresenter(impl: PresenterImpl): Contract.Presenter
}
测试
class MyTestApp : Application(), FeatureOneProvider {
override fun getFeatureOneComponent(): FeatureOneComponent {
return DaggerMockFeatureOneComponent.create()
}
}
@Component(
modules = [MockFeatureOneModules::class]
)
interface MockFeatureOneComponent : FeatureOneComponent {
//I NEED TO MOCK THE SUBCOMPONENT WITH `MockSubcomponent`
}
@Component
object MockFeatureOneModules {
@Provides
fun providesManager() : MyManager = mock(MyManager)
}
//I want to use this module to replace the subcomponent of my activity
@Module
object MockSubcomponent() {
@Provides
fun providesFakePresenter() : FeatureOneContract.Presenter = mock { FeatureOneContract.Presenter::class.java }
}
为了更好地理解问题
当我运行我的测试并放置一个调试器点时,我看到除了 Presenter 之外的所有东西都被模拟了,那是因为 Presenter 在里面
@Subcomponent(modules = [ActivityOneModule::class]
interface Component {
fun inject(activity: FeatureOneActivity)
@SubComponent.Factory
interface Factory {
fun create(@BindsInstance activity: FeatureOneActivity): Component
}
}
@Module
interface ActivityOneModule {
@Binds
fun bindPresenter(impl: PresenterImpl): Contract.Presenter
}
在我的测试组件中,我无权“覆盖”这个子组件,所以一切都被模拟了,但这个子组件我需要这个模拟。
【问题讨论】:
-
您不能覆盖组件。您需要在测试中使用“测试组件”,在生产代码中使用“真实组件”。但是,从您发布的代码中,很难说您在匕首设置中出了什么问题。
-
是的,但是如果我的子组件有
modules=[...],我该如何伪造这些?让我用清晰的代码编辑我的问题 -
@Shark 编辑了我的问题,问题是如何“覆盖”我的生产子组件上的模块并在我的 mockSubcomponent 上使用模拟模块
-
好吧,您的生产子组件没有使用硬编码的模块列表吗?让我尝试发布一些东西,看看你是否抓住了这个想法
-
您是否将
FeatureOneComponent绑定到ApplicationComponent?你确定它绑定的是 TestF1Component 而不是 ProductionF1Component 吗?
标签: android kotlin android-espresso dagger-2 dagger