当我想模拟数据并测试 UI 片段时,doNothing() 不起作用

Posted

技术标签:

【中文标题】当我想模拟数据并测试 UI 片段时,doNothing() 不起作用【英文标题】:doNothing() does not work when i want to mock data and test UI Fragment 【发布时间】:2021-11-02 09:35:14 【问题描述】:

我要用 Espresso 测试 fragment 然后我想模拟 viewmodels 和会员。

在我的viewModel 我有一个void function 像这样:

fun getLoginConfig() 
    viewModelScope.launchApiWith(_loginConfigLiveData) 
       repository.getLoginConfig()
    

在测试fragment 中,当我们从viewModel 调用getLoginConfig() 时,我想用doNothing() 模拟它,但我面对这个error

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here


E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, which is not supported
 3. you are stubbing the behaviour of another mock inside before 'thenReturn' instruction is completed

testFragmentClass 的这一行:

   @Before
    fun setUp() 
        //logOut


        mockVm = mock(SplashVM::class.java)

        loadKoinModules(module 
            single 
                mockVm
            
        )





   doNothing().`when`(mockVm.getLoginConfig()).let 
       mockVm.loginConfigLiveData.postValue(Resource.Success(
           LoginConfigResponse(
               listOf("1"),1,1,"1",true)
       ))
   

【问题讨论】:

在您的测试中,getLoginConfig 返回的是模拟值还是真实值? mockVm 是模拟还是间谍? mockVm 是一个模拟,getLoginConfig()viewModel 中的一个 void func,我们从中调用 API 并用 response 填充 liveData,然后我想填充livedata 和我的假 response 【参考方案1】:

一些事情:

doNothing 什么都不做,这对于模拟中的 void 方法是不必要的。这是默认行为。您只需要 doNothing 用于间谍或已存根的模拟。 如果您希望在响应模拟调用时发生特定的事情,doAnswer is the way to go。 在doVerb 语法中,Mockito 期望那里只有一个变量;表达式不应调用模拟上的方法,否则 Mockito 认为您已经失去兴趣并抛出 UnfinishedStubbingException。

因此你的修复看起来像:

doAnswer 
  mockVm.loginConfigLiveData.postValue(Resource.Success(
    LoginConfigResponse(
      listOf("1"),1,1,"1",true)
  ))
.`when`(mockVm).getLoginConfig()

【讨论】:

感谢您的回答,但loginConfigLiveData 仍然填写真实的response(404 并且失败)并且没有填写虚假的response mockVm.loginConfigLiveData.postValue(Resource.Success( LoginConfigResponse( listOf("1"),1,1,"1",true) )) @milad 你能确认 SplashVM 和 getLoginConfig() 都是 open 吗?老实说,loginConfigLiveData 被完全填充是令人惊讶的,因为mock 不运行构造函数。如果类和方法是 final (Java) 或非 open (Kotlin),这将解释您看到的行为。 是的,之前的错误是关于 SplashVM final class 我用 kotlinlang.org/docs/all-open-plugin.html#gradle 解决的,也许 mock 进程有问题。 @杰夫鲍曼 @miladsalimi 我无能为力;这不是我可以重现或观察自己的问题,所以我所能做的就是在黑暗中猜测。我相信您需要创建minimal reproducible example 以获得更多帮助。 好的,感谢您的指导,@Jeff Bowman

以上是关于当我想模拟数据并测试 UI 片段时,doNothing() 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

无法将特定步骤保存为测试片段

在 UI 测试中将模拟数据插入 Core Data

iCloud UI 测试显示警报登录到 iCloud,尽管已登录并为应用程序启用了 iCloud

没有模拟器或设备的 IOS UI 测试

如何在UI测试中将照片添加到模拟器的相机胶卷

运行 xamarin ui 测试时是不是可以打开 Web 浏览器并在模拟器上进行交互