嗨,我正在尝试模拟我从一个可观察到的响应中得到的响应,该响应从我的演示者类调用的委托(delegate)人从改造中返回,并且出现以下错误:

io.mockk.MockKException:未找到以下答案:LoginPresenter(#1).login(LoginRequest([email protected],password = password123))

这是我的测试代码

 @Test
    fun testKotlinMock(){

        val presenter : LoginPresenter = mockk<LoginPresenter>()

        val delegator = mockk<AccountDelegatorContract>()

        val viewCallback = mockk<LoginContract.LoginViewCallBack>()

        val cookieStore = mockk<PianoCookieStore>()

        val loginRequest = LoginRequest("[email protected]", "password123")
        val customerResponse = CustomerResponse("jon", "richy")

        every { delegator.login(loginRequest) } returns Single.just(Response.success(any()))
        every { delegator.getCustomer() } returns Single.just(customerResponse)
        every { presenter.loginViewCallBack } returns viewCallback
        every { presenter.accountDelegator } returns delegator
        every { presenter.cookieStorage } returns cookieStore

        presenter.login(loginRequest)
    }

我的实际Presenter代码如下所示:
 @Inject
    lateinit var loginViewCallBack: LoginViewCallBack

    @Inject
    lateinit var delegator: DelegatorContract

    @Inject
    lateinit var cookieStorage: CookieStore

    @Inject
    constructor()

    override fun login(loginRequest: LoginRequest) {
        delegator.login(loginRequest)
                .flatMap({ response ->
                     saveCookieAndContinue(response)
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(object : SingleObserver<CustomerResponse>{
                    override fun onSubscribe(d: Disposable) {
                    }

                    override fun onError(e: Throwable) {
                        loginViewCallBack.onErrorLogin(PianoError.ERROR_LOGIN_INVALID)
                        Log.d("JJJ", "login error")
                    }

                    override fun onSuccess(customerResponse : CustomerResponse) {
                        loginViewCallBack.onLoginSuccess(customerResponse)
                        Log.d("JJJ", "login successfully")
                    }
                })
    }

    private fun saveCookieAndContinue(response: Response<Void>): Single<CustomerResponse> {
        if (response.isSuccessful) {
            val headers = response.headers()
            cookieStorage.saveSessionCookies(headers.get(PianoCookieStore.COOKIE_HEADER_SET_NAME)!!)
            return accountDelegator.getCustomer()
        }
        //TODO: Change this to throw a login exception?
       throw RuntimeException()
    }

我基本上想模拟从主代码中看到的注入(inject)的依赖项,然后运行一个快乐的路径单元测试。

当我以没有找到答案的错误 call presenter.login(loginRequest)时失败

这是我正在使用http://mockk.io/的kotlin扩展插件

最佳答案

在您的情况下,您 mock 了要测试的类。您有两种选择:

  • 摆脱了loginPresenter的模拟,只使用原始对象并设置了属性
  • 使用spyk创建 spy 。这介于原始对象和模拟
  • 之间

    抛出异常是因为默认情况下模拟是严格的,它只是不知道如何处理它,因为模拟根本没有初始化为对象。

    在此处阅读有关模拟, spy 和轻松模拟的更多信息:https://blog.kotlin-academy.com/mocking-is-not-rocket-science-mockk-features-e5d55d735a98

    07-25 21:02