Модульный тест 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)
}
Другие вопросы по тегам