微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用条件导航将 androidTest 添加到片段? 配置文件片段登录片段测试可能的解决方案

如何解决如何使用条件导航将 androidTest 添加到片段? 配置文件片段登录片段测试可能的解决方案

我正在尝试将 test navigation 添加conditional navigation 文档中的示例中。

我按照示例创建了一个演示,并在 github 上发布。

演示包含 3 个片段:HomeFragmentProfileFragmentLoginFragment。在 ProfileFragment 中有一个条件检查用户是否已连接。如果用户未连接,他将被发送到 LoginFragment

配置文件片段

@AndroidEntryPoint
class ProfileFragment : Fragment(R.layout.fragment_profile) {
    private val mainviewmodel: Mainviewmodel by activityviewmodels()
    private val navController by lazy { findNavController() }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val currentBackStackEntry = navController.currentBackStackEntry!!
        currentBackStackEntry.savedStateHandle.getLiveData<Boolean>(LoginFragment.LOGIN_SUCCESSFUL)
            .observe(currentBackStackEntry,{ success ->
                if (!success) {
                    val startDestination = navController.graph.startDestination
                    val navOptions = NavOptions.Builder()
                        .setPopUpTo(startDestination,true)
                        .build()
                    navController.navigate(startDestination,null,navOptions)
                }
            })
    }

    override fun onViewCreated(view: View,savedInstanceState: Bundle?) {
        super.onViewCreated(view,savedInstanceState)
        mainviewmodel.user.observe(viewLifecycleOwner,{
            if(!it){
                navController.navigate(R.id.loginFragment)
            }
        })
    }
}

如文档中所述,在 onCreate() 方法中,我观察存储在 LOGIN_SUCCESSFUL 中的 SavedStateHandle 值,以便在用户登录重定向用户

登录片段

@AndroidEntryPoint
class LoginFragment : Fragment() {
    companion object {
        const val LOGIN_SUCCESSFUL: String = "LOGIN_SUCCESSFUL"
    }

    private val viewmodel: Loginviewmodel by viewmodels()
    private val navController by lazy { findNavController() }

    private lateinit var savedStateHandle: SavedStateHandle
    private lateinit var binding: FragmentLoginBinding

    override fun onCreateView(
        inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?
    ): View {
        binding = DataBindingUtil.inflate(inflater,R.layout.fragment_login,container,false)
        binding.viewmodel = viewmodel
        binding.lifecycleOwner = this
        return binding.root
    }

    override fun onViewCreated(view: View,savedInstanceState)
        savedStateHandle = navController.prevIoUsBackStackEntry!!.savedStateHandle
        savedStateHandle.set(LOGIN_SUCCESSFUL,false)

        viewmodel.login.observe(viewLifecycleOwner,ResultObserver {
            if (it.status == Status.ERROR) {
                Snackbar.make(requireView(),it.message ?: "Error",Snackbar.LENGTH_SHORT).show()
            } else if (it.status == Status.SUCCESS) {
                savedStateHandle.set(LOGIN_SUCCESSFUL,true)
                navController.popBackStack()
            }
        })
    }
}

测试

@Test
fun profileFragment_unauthenticated() {
    setAuthentication(false)

    val navController = TestNavHostController(ApplicationProvider.getApplicationContext())

    launchFragmentInHiltContainer<ProfileFragment> {
        navController.setviewmodelStore(viewmodelStore())
        navController.setGraph(R.navigation.nav_main)
        navController.setCurrentDestination(R.id.profileFragment)
        Navigation.setViewNavController(requireView(),navController)
    }
    assertEquals(navController.currentDestination?.id,R.id.loginFragment)
}

因为我使用 Hilt 进行依赖项注入,所以我需要将片段附加到使用 @AndroidEntryPoint 注释的活动:launchFragmentInHiltContainer

在测试期间,我正在创建 TestNavHostController 的实例并将其分配给片段。

问题是我正在访问 navController 方法中的 onCreate,而 navControllerRESUMED 状态期间被实例化(请参阅 FragmentScenario)。导致 java.lang.IllegalStateException: Fragment ProfileFragment ... does not have a NavController set

我知道通过向片段的 navController 添加观察者可以更快地使 viewLifecycleOwnerLiveData 可用。然而,这还不够快。

那么,在这种情况下如何实现测试导航?

可能的解决方

几天后,我一直在寻找一种向我的片段添加测试的方法,我以为我找到了解决方案。这个想法是将 navController 附加到活动。但是,我对结果并不完全满意,这就是我不发布此解决方案作为答案的原因。对于任何感兴趣的人,我将我的解决方添加github repository

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。