问题
I have the following LoginFragment that uses Dagger to inject its fields:
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)
}
I also have a corresponding test that mocks the LoginViewModel according to the documentation from Google: "You can create the fragment and provide it a mock 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)
}
}
The problem is that when the onAttached
method of the fragment is invoked, Dagger overrides the viewModelFactory
with its own object, thus replacing my mock.
How can I prevent Dagger from overriding my mock object?
回答1:
In the android-architecture-components samples on Github Google have an interesting solution.
They inject the activities trough ActivityLifecycleCallbacks. For instrumented tests they use a TestApp that does not register ActivityLifecycleCallbacks so it injects nothing.
Just like in your example the ViewModel.Factory
is package private so in the test you can assign it yourself.
For Fragments
there is FragmentManager.FragmentLifecycleCallbacks class which can be used. Instead of the Fragment
injecting itself in onActivityCreated
your production activity injects the Fragment
using FragmentLifecycleCallbacks
. You can create a testing activity which does not inject the fragment and you can create a mock factory yourself.
来源:https://stackoverflow.com/questions/48099870/disable-dagger-injection-in-tests