Модульный тест Dagger Fragments с FragmentScenario
Я пытаюсь протестировать взаимодействие фрагментов с помощью компонента навигации Android Jetpack и библиотеки тестирования фрагментов. Мое приложение использует java + Dagger2 в качестве DI.
Чтобы проверить навигацию, я создал тест JUnit:
@Test
public void testNavigationToLoginFragment() {
// Create a mock NavController
NavController mockNavController = mock(NavController.class);
// Create a graphical FragmentScenario for the Intro Fragment
FragmentScenario<IntroFragment> introFragmentScenario = FragmentScenario.launchInContainer(IntroFragment.class);
// Set the NavController property on the fragment
introFragmentScenario.onFragment(fragment ->
Navigation.setViewNavController(fragment.requireView(), mockNavController)
);
// Verify that performing a click prompts the correct Navigation action
onView(withId(R.id.button_login)).perform(click());
verify(mockNavController).navigate(R.id.action_intro_fragment_to_login_fragment);
}
Всякий раз, когда я запускаю тест, я получаю следующую ошибку:
java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: No injector factory bound for Class<XXX>
Как я могу вставить туда свой фрагмент? Можно ли использовать DaggerFragments сFragmentScenario
?
IntroFragment
public class IntroFragment extends DaggerFragment{
@Inject
CreateQuoteRecyclerViewAdapter createQuoteRecyclerViewAdapter;
@Inject
public ViewModelProvider.Factory factory;
@inject
public MyViewModel viewModel;
.....
}
MyViewModel.java
class CreateOrSignInViewModel extends BaseViewModel() {
@Inject
public CreateOrSignInBindingState state;
......
}
1 ответ
Объявите следующую функцию в тестовом классе:
@Config(application = TestApp::class)
@RunWith(AndroidJUnit4::class)
@LooperMode(LooperMode.Mode.PAUSED)
class MyFragmentTest {
private val createQuoteRecyclerViewAdapter: CreateQuoteRecyclerViewAdapter = mock()
private val viewModel: MyViewModel = mock()
private fun launchFragment(): FragmentScenario<MyFragment> {
return launchFragmentInContainer(factory = object : FragmentFactory() {
override fun instantiate(classLoader: ClassLoader, className: String): Fragment {
return MyFragment().apply {
createQuoteRecyclerViewAdapter = this@MyFragmentTest.createQuoteRecyclerViewAdapter
viewModel = this@MyFragmentTest.viewModel
// assign other deps here as per your needs
}
}
}, themeResId = R.style.AppTheme)
}
}
куда TestApp
объявляется так:
class TestApp : Application()
Это может потребоваться, чтобы избежать ошибок, которые могут произойти в вашем пользовательском классе приложения. onCreate()
метод, в котором строится Dagger tree.
После такой настройки вы можете начать писать свой модульный тест:
@Test
fun `navigation to login screen is correctly performed`() {
val navController: NavController = mock()
val scenario = launchFragment()
scenario.onFragment {
Navigation.setViewNavController(it.requireView(), navController)
}
onView(withId(R.id.button_login)).perform(click())
verify(mockNavController).navigate(R.id.action_intro_fragment_to_login_fragment)
}