gpt4 book ai didi

Android 使用 Hilt 使用模拟 ViewModel 测试 Fragmen

转载 作者:行者123 更新时间:2023-12-04 23:54:52 27 4
gpt4 key购买 nike

我正在使用 Hilt 开发一个应用程序,一切正常,但是当我尝试在运行于 Android P 以下的设备上运行一些 Espresso 测试时,我遇到了一个问题。
当我尝试模拟(使用 Mockk)ViewModel 以便我可以对我的 Fragment 进行单元测试时,问题就出现了。当 Fragment 尝试实例化 ViewModel 时,我在创建 ViewModel 时收到 NullPointerException。 NPE 被抛出方法 setTagIfAbsent .问题是这个方法是包私有(private)的,你可以在 ViewModel source code 上看到。 ,所以不能在 Android < P 上模拟。
我尝试过使用 Kotlin All-Open plugin ,它有助于模拟 ViewModel 并将其存入公共(public)方法。我尝试 stub setTagIfAbsent通过使用 mockk 私有(private) stub ,如下所示:

every{
myViewModelMock["setTagIfAbsent"](any<String>,any())
} answers {secondArg()}
但是当 setTagIfAbsent被调用,真正的方法被调用,抛出 NPE,因为 ViewModel.mBagOfTags为空,因为该类是模拟的。
其余代码如下:
View 模型:
@OpenForTesting
@HiltViewModel
class MyViewModel @Inject constructor MyViewModel(private val dependency: Dependency): ViewModel(){
//Rest of the code
}
分段:
@AndroidEntryPoint
class MyFragment: Fragment(){
private val viewModel: MyViewModel by viewModels()
//Rest of the code
}
测试类:
@HiltAndroidTest
@RunWith(AndroidJUnit4::class)
class MyFragmentTest {

@Bind
@MockK
lateinit var viewModel: MyViewModel

@get:Rule
var hiltRule = HiltAndroidRule(this)

@Before
fun prepareTest(){
MockkAnnotations.init(this)
hiltRule.inject()
launchFragmentInHiltContainer<MyFragment>()
}

@Test
fun testThatWillMakeAViewModelInvokation(){
onView(withId(R.id.button)).perform(click())
//Assume that button will make the ViewModel be called and created by the delegate
//When this happens the NPE is thrown
}
}
方法launchFragmentInHiltContainer来自 here (Hilt sample app) .
如果您查看 Mockk Android documentation据说 有谁知道我该如何解决这个问题或如何修复测试?
提前致谢。

最佳答案

而不是 mock setTagIfAbsent你可以模拟mBagOfTags在已经模拟的 ViewModel 实例上使用反射。

setInternalFieldValue(mockedViewModel, "mBagOfTags", HashMap<String, Any>())
fun setInternalFieldValue(target: Any, fieldName: String, value: Any, javaClass: Class<in Any> = target.javaClass) {
try {
val field = javaClass.getDeclaredField(fieldName)
field.isAccessible = true
field.set(target, value)
} catch (exception: NoSuchFieldException) {
val superClass = javaClass.superclass
if (superClass != null) {
setInternalFieldValue(target, fieldName, value, superClass)
} else {
throw RuntimeException("Field $fieldName is not declared in a hierarchy of this class")
}
}
}

关于Android 使用 Hilt 使用模拟 ViewModel 测试 Fragmen,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68351244/

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