1

我正在写一个单元测试。下面是我的代码。该架构是使用 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)

登录视图模型类:

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

 fun getLoginState(): LiveData<Outcome<String>> = loginState
 

LoginViewModelTest 类:

 @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")) } 
    }

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

4

1 回答 1

3

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

指定匹配的呼叫应答范围为应答范围的代码块

我刚刚发布了这个:

every { mockObserver!!.onChanged(any()) } answers {}

在以下测试功能中,它起作用了。

@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")) } 
    }

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

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

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

如果我错了,请通过评论纠正我,我会更新它。

于 2020-09-07T10:42:28.400 回答