如何使用 mockito 在我的 retrofit2 演示器上实施单元测试?

How to Implement Unit test on my retrofit2 presenter using mockito?

我想通过对我的代码使用 mockito 依赖项来进行单元测试。它总是失败,因为 view.processMatchData(data) 和 view.hideLoading() 在此演示代码中处于闭包部分,因此单元测试不会检测到它们。请有人帮我解决这个问题。

open class MatchSearchPresenter(
    private val view: MatchSearchView,
    private val apiService: ApiService,
    private val cari : String
) {
    fun searchMatch() {
        view.showLoading()
        apiService.loadSearchMatch(cari).enqueue(object : Callback<MatchSearchResponseModel> {
                override fun onResponse(call: Call<MatchSearchResponseModel>, response: Response<MatchSearchResponseModel>)
                {
                    if (response.isSuccessful) {
                        val data = response.body()!!
                        view.processMatchData(data)
                    }
                    view.hideLoading()
                }

                override fun onFailure(call: Call<MatchSearchResponseModel>, error: Throwable)
                {
                    Log.e("Error", error.message)
                    view.hideLoading()
                }
        })
    }
}

这是我的单元测试:

class MatchSearchPresenterTest {
    @Mock
    private lateinit var view: MatchSearchView
    @Mock
    private lateinit var apiService: ApiService
    @Mock
    private lateinit var teamPresenter: MatchSearchPresenter
    @Mock
    private lateinit var call: Call<MatchSearchResponseModel>
    @Mock
    private lateinit var something: Callback<MatchSearchResponseModel>


    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        val kata = "Man United"
        teamPresenter = MatchSearchPresenter(view, apiService, kata )
    }
    @Test
    fun searchMatch() {
        val teamId = "Man United"
        val teams: MutableList<PrevMatchData> = mutableListOf()
        val data = MatchSearchResponseModel(teams)

        teamPresenter.searchMatch()

        argumentCaptor<MatchSearchView>().apply {
            Mockito.verify(apiService.loadSearchMatch(teamId).enqueue(something))
            firstValue.processMatchData(data)
            firstValue.hideLoading()
        }

        Mockito.verify(view).showLoading()
        Mockito.verify(view).processMatchData(data)
        Mockito.verify(view).hideLoading()
    }
}

但是显示这样的消息是行不通的:

java.lang.NullPointerException
    at com.example.footballleaguecataloguefourth.ui_bottom_navigation.schedule.match_search.MatchSearchPresenter.searchMatch(MatchSearchPresenter.kt:19)
    at com.example.footballleaguecataloguefourth.ui_bottom_navigation.schedule.match_search.MatchSearchPresenterTest.searchMatch(MatchSearchPresenterTest.kt:41)

我想你在这里想要的是让 ApiService 调用 return 的调用在排队后立即调用正确的方法。

为此,您可以使用 Mockito 的 thenAnswer - Here's 示例。在你的情况下,你可以试试这个:

Mockito.`when`(call.enqueue(Mockito.any())).thenAnswer {
    (it.getArgument(0) as Callback<MatchSearchResponseModel>).onResponse(
        call,
        Response.success(MatchSearchResponseModel(/*whatever is needed to build this object*/))
    )
}

在这里,您要确保一旦使用任何参数调用 call.enqueue,它将立即调用 onResponse 方法并返回成功响应。您可以对错误执行类似的操作,也可以调用 onFailure.

您需要做的最后一件事是确保您的 api 服务 return 是配置的模拟 call:

 Mockito.`when`(apiService.loadSearchMatch(kata)).thenReturn(call)

我会把这个放在每个测试中。所以在你调用你的演示者方法之前,我会像这样配置模拟。

现在,调用 teamPresenter.searchMatch(),应该调用 apiService.loadSearchMatch(cari),这将 return 一旦入队的模拟调用将调用传递的回调的 onResponse 方法。

最后,您可能已经注意到 when 实际上是用反引号书写的。这是因为它是一个需要转义的 kotlin 关键字。不仅出于这个原因,还有更多原因,您可以考虑使用 Mockito Kotlin,这是一个极好的 kotlin 库,包装了 mockito,让生活变得更轻松。