将模拟对象提供给另一个模拟对象构造函数?

时间:2017-11-16 03:34:38

标签: java android unit-testing kotlin mockito

首次进行单元测试,并使用Mockito。我不确定我是否正在考虑正确测试这个问题。情况如下:

在我的Android应用中,我使用的是Model-View-Presenter。我正在尝试在我的presenter类中调用一个名为validateCredential(serviceManager: ServiceManager, email: String, password: String)的方法来查看我传递给它的服务管理器最终是否会通过mockito验证它来调用回调(此方法由视图调用)。

// method in presenter class
override fun validateCredential(serviceManager: ServiceManager, email: String, password: String) {
    loginModel = LoginModel(email, password)
    serviceManager.getParent(email, password)
    serviceManager.execute()
}

// callback implemented by presenter class
private fun handleLoginResult(result: ServiceManager.RequestResult, data: ByteArray, responseCode: Int, optionalParam: String) {
    ...
    mView.startHomeScreen()
}

presenter类还实现了一个提供给IServiceAsyncTaskCallback构造函数的回调接口(serviceManager)。我在这个特定的单元测试中想要的是验证是否mView.startHomeScreen()被调用。

问题:

  • Android单元测试似乎要求ServiceManager被模拟(ServiceManager扩展抽象类AsyncTask),因为当我调用execute()时,如果没有模拟,则测试lib的Android单元将抛出异常。
  • 但是,如果我模拟ServiceManager,我不能为构造函数提供两个必要的参数,如果我正确理解单元测试,那么应该嘲笑它。构造函数的两个参数是接口回调(它是演示者类),以及负责通过http发送JSON的类对象。这两个都应该被嘲笑,对吗?因为在单元测试中,您不希望这些依赖项实际进行HTTP调用或调用回调,对吧?
  • 我似乎在想这个。我真正想要的是看看我的视图对象是否传递给演示者,调用startHomeScreen(),所以我应该忘记测试validateCredentialMethod()并直接调用handleLoginResult(...)。这比上面的路线好吗?
  • 然而,另一个问题是,即使我直接调用handleLoginResult(...)来测试是否调用传递给presenter的模拟视图,该方法代码也包含对JSONObject的调用,这是与Android相关的代码,因为它属于android.jar文件,它会抛出异常因为它没有被嘲笑!我是否应该为此提供注射?!

我迷失了如何测试这个。验证模拟视图是否调用了startHomeScreen()

的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

问题是你试图在一个单元测试中测试两个单独的类,这使它不是一个单元测试。

使用您当前的设置,您似乎希望拥有3个不同的测试用例,分为2个不同的类别(组成名称,尝试尽可能明确地说明其内容):

  • PresenterTest

    • testThatServiceManagerIsExcecutedOnValidateCredential
    • testThatStartHomeScreenIsCalledWhenHandlingLoginResult
  • ServiceManagerTest

    • testCallbackIsCalledOnExcecuted