如何使用 FragmentScenario 测试 DaggerFragment?

Arc*_*nes 2 android dagger-2 android-fragmentscenario

我有一个简单的Fragment像这样:

class SomeFragment : DaggerFragment() {
    ...
}
Run Code Online (Sandbox Code Playgroud)

现在我想Fragment用它来测试这个FragmentScenario

class LoginFragmentTest {

    @Test
    fun test() {
        launchFragmentInContainer<SomeFragment>()
        onView(withId(R.id.someButton))
            .check(matches(isDisplayed()))
    }

}
Run Code Online (Sandbox Code Playgroud)

但每次我尝试测试时总是:

java.lang.IllegalArgumentException:找不到 <...SomeFragment> 的注入器

我怎样才能正确运行测试?有人可以帮我吗?

jsa*_*mol 5

我找到了两种方法来解决这个问题:

我认为第一种方法更干净,建议使用它而不是后者,但我将描述这两种方法,以便您可以做出自己的选择。


构建风味typealias

  1. 创建两种产品口味,mock并且prod

app/build.gradle

android {
    ...
    productFlavors {
        prod
        mock {
            applicationIdSuffix '.mock'
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 然后根据口味设置typealias,我们称之为BaseFragment

prod味道, app/src/prod/com.example.mypackage/BaseFragment.kt

typealias BaseFragment = DaggerFragment
Run Code Online (Sandbox Code Playgroud)

mock味道,app/src/mock/com.example.mypackage/BaseFragment.kt

typealias BaseFragment = Fragment
Run Code Online (Sandbox Code Playgroud)
  1. 最后BaseFragment在片段中使用别名:
class SomeFragment : BaseFragment() {
   ...
}
Run Code Online (Sandbox Code Playgroud)
  1. FragmentScenario要使用从prod*构建变体切换到构建变体来测试代码mock*,并设置应该注入测试类中某处的所有依赖项(例如使用模拟)

拥有DaggerFragment并测试片段的变体

  1. 创建您自己的DaggerFragment(根据实际dagger.android.support.DaggerFragment实现):
abstract class DaggerFragment() : Fragment(), HasAndroidInjector {

    @Inject
    lateinit var androidInjector: DispatchingAndroidInjector<Object>

    override fun onAttach(context: Context) {
        injectMembers()
        super.onAttach(context)

    override fun androidInjector(): AndroidInjector<Object> = androidInjector

    protected open fun injectMembers() = AndroidSupportInjection.inject(this)
}
Run Code Online (Sandbox Code Playgroud)
  1. 扩展您的DaggerFragment实现并设置片段open
open class SomeFragment : DaggerFragment() {
    ...
}
Run Code Online (Sandbox Code Playgroud)
  1. 出于测试目的创建片段的另一个实现并覆盖该injectMembers方法:
class TestSomeFragment : SomeFragment() {

    override injectMembers() {
        /* you can manually inject dependencies and mocks here */
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. TestSomeFragment在您的测试中使用。