首页 > 解决方案 > 使用 Dagger2、Espresso 和 Mockito 对 MVVM 架构进行 Android UI 测试

问题描述

我第一次尝试将 UI 测试添加到应用程序中,我正在考虑使用 espresso。

该应用程序将 Dagger2 用于 DI,并@Inject为应该可注入的类和AndroidInjection/AndroidSupportInjection在屏幕中(Activity / Fragment)添加注释。

class Application : android.app.Application(), HasActivityInjector, HasServiceInjector {
...
    override fun onCreate() {
        super.onCreate()
        initDagger()
        Timber.d("Application initialized successfully!")
    }

    protected open fun initDagger() {
        Components.initialize(this)
    }
}

object Components : ComponentFactory {
    private lateinit var sComponent: AppComponent

    fun initialize(app: Application) {
         sAppComponent = DaggerAppComponent.builder()
            .applicationModule(ApplicationModule(this))
            .build()
    }
    // overrides
}

interface ComponentFactory {
    fun app(): AppComponent
    fun authenticated(): AuthenticatedComponent
}

接下来是Components 和Modules。AppActivitiesModuleAuthenticatedActivitiesModule@ContributesAndroidInjector用于屏幕的类。

@Singleton
@Component(modules = [AppModule::class, AppActivitiesModule::class, AndroidInjectionModule::class, AndroidSupportInjectionModule::class])
interface AppComponent {

    fun authenticatedComponentBuilder(): AuthenticatedComponent.Builder

    fun inject(app: Application)

    @Component.Builder
    interface Builder {
        fun build(): AppComponent

        fun applicationModule(applicationModule: ApplicationModule): Builder
    }
}

@Module
open class AppModule(private val application: Application) {
// some @Provides
}
@AuthenticatedScope
@Subcomponent(modules = [AuthenticatedModule::class, AuthenticatedActivitiesModule::class])
interface AuthenticatedComponent {

    fun inject(application: Application)

    @Subcomponent.Builder
    interface Builder {
        fun userModule(module: UserModule): Builder

        fun build(): AuthenticatedComponent
    }
}


@Module
class AuthenticatedModule(private val userId: Long,
                          private val userRole: User.Role) {
// Some @Provides @AuthenticatedScope
}

一个典型的用例是:

@Singleton
class AppLevelService 
@Inject constructor(...) { ... }

@AuthenticatedScope
class AuthenticatedLevelServices 
@Inject constructor(...) { ... }

class ViewModel 
@Inject constructor(private val appService: AppLevelService,
                    private val authService: AuthenticatedLevelServices) { ... }

class MyActivity : BaseActivity {
    @Inject 
    lateinit var vmProvider: Provide<ViewModel>

    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
    }
}

如何为这种“类型”的匕首使用进行测试设置?

我发现了很多使用 dagger2 进行测试的示例,但对于@Provides注释,我认为应该有一种方法可以使用@Inject.

我试过了DaggerMock,但我得到:

您必须使用 @Provides 注释方法而不是使用 @Inject 注释来定义覆盖的对象

并不是说它会影响任何事情,但我也在使用带有DexOpener.

用于测试此设置的任何想法或好的文档/示例?

标签: androidmockitodagger-2android-espressodagger

解决方案


推荐阅读