收到错误 MockKException:找不到答案:Observer(#8).onChanged Android

Ahm*_*aiz 5 android mockk android-unit-testing

我正在写一个单元测试。下面是我的代码。该架构是使用 Dagger2 的 MVVM。我正在调用 LoginViewModel 中的登录函数,该函数通知 getLoginState 函数。我收到的错误是:

错误:

 io.mockk.MockKException: no answer found for: Observer(#8).onChanged(Success(data=))
    
        at io.mockk.impl.stub.MockKStub.defaultAnswer(MockKStub.kt:90)
Run Code Online (Sandbox Code Playgroud)

登录ViewModel类:

 fun logIn(phone: String, phoneCode: String) {
        loginState.value = Outcome.success("")
}

 fun getLoginState(): LiveData<Outcome<String>> = loginState
 
Run Code Online (Sandbox Code Playgroud)

登录ViewModelTest类:

 @RelaxedMockK
    var SUT: LoginViewModel? = null

    @Mock
    var loginInteractor: LoginInteractor? = null

    @Mock
    var textValidator: TextValidator? = null

    @Mock
    var textProvider: TextProvider? = null

    @Mock
    var blinkUserPreferences: BlinkUserPreferences? = null

    @get:Rule
    var rule: TestRule = InstantTaskExecutorRule()

    @RelaxedMockK
    var mockObserver: Observer<Outcome<String>>? = null
    @Before
        fun setUp() {
    
            MockKAnnotations.init(this, relaxUnitFun = true)
             SUT = spyk(
                 LoginViewModel(
                         mockk<LoginInteractor>(),
                         mockk<TextValidator>(relaxed = true),
                         mockk<TextProvider>(),
                         mockk<BlinkUserPreferences>()))
            mockObserver = mockk<Observer<Outcome<String>>>()
             SUT!!.getLoginState().observeForever(mockObserver!!)
    
        }
     @Test
        fun logIn() {
            //Arrange 
            every {SUT!!.getLoginState().value} returns Outcome.success("")
    
            //Act 
            SUT!!.logIn("89989676","89998")

        //Assert  
        verify() { mockObserver!!.onChanged(Outcome.success("abc")) } 
    }
Run Code Online (Sandbox Code Playgroud)

问题: 在验证中,为什么 onChanged 方法没有被调用,或者没有找到 Observer().onChanged 的​​答案意味着什么,我如何通知我的 onChanged 方法以便我可以验证它?

Ahm*_*aiz 9

看完这个: https: //mockk.io/#answers。它说

指定匹配的调用使用范围为应答范围的代码块应答

我刚刚发布了这个:

every { mockObserver!!.onChanged(any()) } answers {}
Run Code Online (Sandbox Code Playgroud)

在下面的测试函数中它起作用了。

@Test
 fun logIn() {
            //Arrange 
            every { mockObserver!!.onChanged(any()) } answers {}
            every {SUT!!.getLoginState().value} returns Outcome.success("abc")
    
            //Act 
            SUT!!.logIn("89989676","89998")

            //Assert  
            verify() { mockObserver!!.onChanged(Outcome.success("abc")) } 
    }
Run Code Online (Sandbox Code Playgroud)

根据我的理解,如果你是mockk一个函数,并且你想使用它的特定函数,你必须使用表达式every告诉框架它会这样做answer,因为框架需要知道它需要回答一些问题

如果您希望所有行为函数也应该在其实现中添加模拟,那么您必须为spyk您的类添加行为,以便它也能获得行为,然后您可以轻松地使用该函数,而无需使用表达式every

请注意,every表达式用于许多情况,例如从该函数中获取模拟结果,或者只需要告诉框架该函数应该answers这样。

如有错误请评论指正,我会更新。