在测试中禁用Dagger注入

时间:2018-01-04 16:47:42

标签: android unit-testing mockito dagger-2

我有以下LoginFragment使用Dagger注入其字段:

class LoginFragment : DaggerFragment() {

    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        viewModel = ViewModelProviders.of(this, viewModelFactory)
                .get(LoginViewModel::class.java)
    }

我还有一个相应的测试,根据Google的文档嘲笑LoginViewModel:“你可以创建片段并为它提供一个模拟的ViewModel。”

@MediumTest
@RunWith(AndroidJUnit4::class)
class LoginFragmentTest {

    @Mock
    private lateinit var viewModel: LoginViewModel

    @Before
    fun setUp() {
        loginFragment = LoginFragment()

        loginFragment.viewModelFactory = createMockViewModelFactory(viewModel)

        activityRule.activity.setFragment(loginFragment)
    }
}

问题在于,当调用片段的onAttached方法时,Dagger会用自己的对象覆盖viewModelFactory,从而替换我的模拟。

如何防止Dagger覆盖我的模拟对象?

1 个答案:

答案 0 :(得分:4)

在Github的android-architecture-components示例中,Google提供了一个有趣的解决方案。

他们inject活动通过ActivityLifecycleCallbacks。对于检测测试,他们使用TestApp注册ActivityLifecycleCallbacks,因此它不会注入任何内容。

就像在你的例子中ViewModel.Factory是包私有的,所以在测试中你可以自己分配它。

对于Fragments,可以使用FragmentManager.FragmentLifecycleCallbacks类。 Fragment onActivityCreated注入Fragment生产活动,而不是FragmentLifecycleCallbacks使用let x = "http://localhost:3001/build/?videoUrl=bitcoin.vid.com/money#/"; console.log((new URL(x)).searchParams.get("videoUrl"));注入videoUrl。您可以创建一个不注入片段的测试活动,您可以自己创建一个模拟工厂。