【问题标题】:Testing Retrofit with coroutines使用协程测试改造
【发布时间】:2019-06-11 12:09:15
【问题描述】:

您如何正确地使用RetrofitCoroutines 测试Http 请求/响应?

我正在使用最新的Retrofit 版本:2.6.0,它支持suspend 功能。

编辑

我还提供了一些易于实现的代码:

API接口

@GET
suspend fun getCountriesListAsync(@Url url: String): Response<ArrayList<Country>>

一些存储库

suspend fun  makeCountryApiCallAsync(): Response<ArrayList<Country>> =
    treasureApi.getCountriesListAsync(COUNTRIES_API_URL)

ViewModel上的实现:

private suspend fun makeCountriesApiCall() {
        withContext(Dispatchers.Main) {
            switchProgressBarOn()
        }
        try {
            val countriesListResponse = setupRepository.makeCountryApiCallAsync()
            if (countriesListResponse.isSuccessful) {
                withContext(Dispatchers.Main) {
                    switchProgressOff()
                    countriesList.value = countriesListResponse.body()
                }
            } else {
                withContext(Dispatchers.Main) {
                    showErrorLayout()
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
            withContext(Dispatchers.Main) {
                showErrorLayout()
            }
        }
    }

【问题讨论】:

    标签: android retrofit2 android-testing kotlin-coroutines


    【解决方案1】:

    我想你是在问如何测试协程?

    无论您的逻辑在哪里,您都应该进行测试。正如我所见,您的存储库不包含 Api 调用之外的任何逻辑。如果是这种情况,您无法针对实时数据进行测试,因为它不一致,但您可以使用 WireMock 或 Mockito 模拟某些结果并尝试使其通过您的逻辑。

    coroutine test support可以看一下。

    这是一个例子

    协程测试的必要条件(你可以不这样做,但这样做会容易得多)

    testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.0-M1'

    可选,用于模拟我的通话结果

    testImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0'

    以你给出的为例

    @ExperimentalCoroutinesApi
    class ViewModelTest {
        private val testDispatcher = TestCoroutineDispatcher()
        private val testScope = TestCoroutineScope(testDispatcher)
    
        @Before
        fun before() {
            Dispatchers.setMain(testDispatcher)
        }
    
        @After
        fun after() {
            Dispatchers.resetMain()
            testScope.cleanupTestCoroutines()
        }
    
        @Test
        fun testYourFunc() = testScope.runBlockingTest {
            val mockRepo = mock<MyRepository> {
                onBlocking { makeCountryApiCallAsync("") } doReturn Response.success(listOf())
            }
    
            val viewModel = TheViewModel(mockRepo)
    
            val result = viewModel.makeCountriesApiCall() // Or however you can retrieve actual changes the repo made to viewmodel
    
            // assert your case
        }
    }
    

    【讨论】:

    • 是的,这似乎是正确的答案,因为我只是在面对那个广告。但是,我确实遇到了runBlockingTest 的问题,只是留在了runBlocking
    猜你喜欢
    • 2018-06-13
    • 2021-05-21
    • 1970-01-01
    • 2020-07-11
    • 1970-01-01
    • 2015-05-06
    • 1970-01-01
    • 1970-01-01
    • 2020-04-24
    相关资源
    最近更新 更多