android - 如何在使用 Android Hilt 进行仪器测试期间将模拟的 ViewModel 注入 Fragment?
问题描述
我很难在 Android 上进行仪器测试。
目标:在Instrumented 测试ViewModel
期间注入一个 mocked 。Fragment
语境:
MyViewModel
是使用Hilt Jetpack 集成和@ViewModelInject
注释构建的,如下所示:
class OverviewViewModel @ViewModelInject constructor(
private val coroutineScopeProvider: CoroutineScope?,
private val repository: Repository
): ViewModel() {
private val coroutineScope = getViewModelScope(coroutineScopeProvider)
val isLogged = repository.isLogged
val session = repository.session
fun logout() {
coroutineScope.launch {
repository.logout()
}
}
}
fun ViewModel.getViewModelScope(coroutineScope: CoroutineScope?) =
coroutineScope ?: this.viewModelScope
// Need to do that to be able to test the viewModel
@Module
@InstallIn(ActivityComponent::class)
object CoroutineModel {
@Provides
fun provideViewScopeModel(): CoroutineScope? = null
}
我的片段使用ViewModel
如下:
@AndroidEntryPoint
class OverviewFragment : Fragment() {
private val viewModel: OverviewViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val binding = DataBindingUtil.inflate<FragmentOverviewBinding>(inflater,
R.layout.fragment_overview,container,false)
binding.viewModel = viewModel
binding.lifecycleOwner = viewLifecycleOwner
binding.loginButton.setOnClickListener {
val intent = SessionUtil.getAuthIntent()
startActivity(intent)
}
binding.logoutButton.setOnClickListener {
viewModel.logout()
}
return binding.root
}
}
我试过的:
我想注入一个模拟OverviewViewModel
,这样我就可以隔离Fragment
测试,检查按钮单击事件是否与它正确连接。
到目前为止,这是我的测试:
@HiltAndroidTest
@RunWith(AndroidJUnit4::class)
class OverviewFragmentTest {
val hiltRule = HiltAndroidRule(this)
@get: Rule
val testRules = RuleChain
.outerRule(hiltRule)
.around(ActivityTestRule(MainActivity::class.java))
val mockViewModel = mockkClass(OverviewViewModel::class)
val mockIsLogged = MutableLiveData<Boolean>()
@BindValue @JvmField
val viewModel: OverviewViewModel = mockViewModel
@Before
fun setup () {
clearAllMocks()
hiltRule.inject()
}
@Test
fun Given_nothing_When_clicking_login_button_Then_login_intent_triggers() {
every {viewModel.isLogged} returns mockIsLogged
mockIsLogged.postValue(false)
Intents.init()
every { SessionUtil.getAuthIntent() } returns Intent(Intent.ACTION_VIEW, Uri.parse("https://toto"))
launchFragmentInHiltContainer<OverviewFragment>()
onView(withId(R.id.login_button)).perform(click())
verify {
SessionUtil.getAuthIntent()
}
intended(
hasAction(Intent.ACTION_VIEW)
)
intended(
hasData("https://toto")
)
Intents.release()
}
@Test
fun Given_null_response_When_clicking_logout_button_Then_call_toaster() {
every {viewModel.isLogged} returns mockIsLogged
mockIsLogged.postValue(true)
launchFragmentInHiltContainer<OverviewFragment>()
onView(withId(R.id.logout_button)).perform(click())
verify {
mockViewModel.logout()
}
}
}
实际:似乎片段仍然使用真实的ViewModel
,因为即使发布一个值(例如mockIsLogged.postValue(false)
),片段内的观察者仍然记录true
(来自真实模型的值)
解决方案
推荐阅读
- git - 远程分支和本地分支之间的差异
- javascript - 正确改写打字稿签名,返回自定义类型而不是方法所需的严格签名
- django - django 在 has_perm() 中使用模板标签
- php - 查找两个不同列中的两个日期之间是否存在条目?
- oop - 内省 NQP 角色
- linux - 在亚马逊管理的区块链上将成员添加到现有的超级账本 Fabric 1.2 网络
- nim-lang - defer 之后的语句是否在早期中断迭代时被调用?
- python-3.x - EOFError,即使在尝试了 try 和 except 块之后
- java - 无法解析 pom.xml 依赖项 - Eureka DiscoveryClient
- angular - 在导航到 Angular 中的路线之前,函数没有检查条件