有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

带有碎片场景的java单元测试匕首片段

我正在尝试使用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>

我怎样才能把我的碎片注射到那里?可以将匕首碎片与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) 个答案

  1. # 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()方法中,其中正在构造匕首树

    完成此设置后,您可以开始编写单元测试:

    @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)
    }