gpt4 book ai didi

android - 测试导航组件 : "does not have a NavController"

转载 作者:行者123 更新时间:2023-11-29 16:28:00 27 4
gpt4 key购买 nike

我正在实现 Espresso 测试。我正在使用带有 NavGraph 范围 ViewModel 的 fragment 。问题是,当我尝试测试 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

最佳答案

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供引用。


docs 中提到了另一种方法还有:

    // Create a graphical FragmentScenario for the TitleScreen
val titleScenario = launchFragmentInContainer<TitleScreen>()

// Set the NavController property on the fragment
titleScenario.onFragment { fragment ->
Navigation.setViewNavController(fragment.requireView(), mockNavController)
}

如果在 onViewCreated()(包含)之前与 NavController 发生交互,则此方法将不起作用。使用这种方法 onFragment() 会在生命周期中设置模拟 NavController 太迟,导致 findNavController() 调用失败。作为适用于所有情况的统一方法,我建议使用第一种方法。

关于android - 测试导航组件 : "does not have a NavController",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58950325/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com