问题描述
我很难在Android上进行仪器化测试。
目标:在viewmodel
仪器化测试中注入模拟的Fragment
。
上下文:
我的viewmodel
使用Hilt Jetpack integrations和@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)
)时,该片段内的观察者仍会记录{{ 1}}(值来自真实模型)
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)