测试导航组件:“没有NavController”

问题描述 投票:0回答:2

我正在执行Espresso测试。我正在使用NavGraph范围为ViewModel的片段。问题是当我尝试测试Fragment时,我得到了IllegalStateException,因为Fragment没有设置NavController。如何解决此问题?

class MyFragment : Fragment(), Injectable {

    private val viewModel by navGraphViewModels<MyViewModel>(R.id.scoped_graph){
        viewModelFactory
   }

    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory
    //Other stuff
}

测试类:

class FragmentTest {

    class TestMyFragment: MyFragment(){
        val navMock = mock<NavController>()

        override fun getNavController(): NavController {
            return navMock
        }
    }

    @Mock
    private lateinit var viewModel: MyViewModel
    private lateinit var scenario: FragmentScenario<TestMyFragment>

    @Before
    fun prepareTest(){
        MockitoAnnotations.initMocks(this)

    scenario = launchFragmentInContainer<TestMyFragment>(themeResId = R.style.Theme_AppCompat){
        TestMyFragment().apply {
            viewModelFactory = ViewModelUtil.createFor(viewModel)
        }
    }

    // My test
}

我得到的异常:

java.lang.IllegalStateException: View android.widget.ScrollView does not have a NavController setjava.lang.IllegalStateException
android android-espresso android-testing android-architecture-components android-viewmodel
2个回答
1
投票

docs中可以看到,这是建议的方法:

// Create a mock NavController
val mockNavController = mock(NavController::class.java)

scenario = launchFragmentInContainer<TestMyFragment>(themeResId = R.style.Theme_AppCompat) {
    TestMyFragment().also { fragment ->     
        // In addition to returning a new instance of our Fragment,
        // get a callback whenever the fragment’s view is created
        // or destroyed so that we can set the mock NavController
        fragment.viewLifecycleOwnerLiveData.observeForever { viewLifecycleOwner ->
            if (viewLifecycleOwner != null) {
                // The fragment’s view has just been created
                Navigation.setViewNavController(fragment.requireView(), mockNavController)
            }
        }
    }
}

此后,您可以像这样对模拟的mockNavController进行验证:

verify(mockNavController).navigate(SearchFragmentDirections.showRepo("foo", "bar"))

请参见architecture components sample以供参考。


0
投票

您缺少设置NavController

testFragmentScenario.onFragment {
            Navigation.setViewNavController(it.requireView(), mockNavController)
        }
© www.soinside.com 2019 - 2024. All rights reserved.