gpt4 book ai didi

android - 使用 MockWebServer 暂停功能测试

转载 作者:行者123 更新时间:2023-12-04 11:57:22 26 4
gpt4 key购买 nike

我正在测试使用 MockWebServer 的挂起函数返回结果的 api,但它不适用于 runBlockingTest、testCoroutineDispatcher、testCorounieScope,除非 launch使用了builder,为什么?

abstract class AbstractPostApiTest {

internal lateinit var mockWebServer: MockWebServer

private val responseAsString by lazy {
getResourceAsText(RESPONSE_JSON_PATH)
}

@BeforeEach
open fun setUp() {
mockWebServer = MockWebServer()
println("AbstractPostApiTest setUp() $mockWebServer")
}


@AfterEach
open fun tearDown() {
mockWebServer.shutdown()
}

companion object {
const val RESPONSE_JSON_PATH = "posts.json"
}


@Throws(IOException::class)
fun enqueueResponse(
code: Int = 200,
headers: Map<String, String>? = null
): MockResponse {

// Define mock response
val mockResponse = MockResponse()
// Set response code
mockResponse.setResponseCode(code)

// Set headers
headers?.let {
for ((key, value) in it) {
mockResponse.addHeader(key, value)
}
}

// Set body
mockWebServer.enqueue(
mockResponse.setBody(responseAsString)
)

return mockResponse
}


}


class PostApiTest : AbstractPostApiTest() {

private lateinit var postApi: PostApiCoroutines

private val testCoroutineDispatcher = TestCoroutineDispatcher()

private val testCoroutineScope = TestCoroutineScope(testCoroutineDispatcher)

@BeforeEach
override fun setUp() {
super.setUp()

val okHttpClient = OkHttpClient
.Builder()
.build()

postApi = Retrofit.Builder()
.baseUrl(mockWebServer.url("/"))
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build()
.create(PostApiCoroutines::class.java)


Dispatchers.setMain(testCoroutineDispatcher)

}

@AfterEach
override fun tearDown() {
super.tearDown()

Dispatchers.resetMain()
try {
testCoroutineScope.cleanupTestCoroutines()
} catch (exception: Exception) {
exception.printStackTrace()
}
}

@Test
fun `Given we have a valid request, should be done to correct url`() =
testCoroutineScope.runBlockingTest {

// GIVEN
enqueueResponse(200, RESPONSE_JSON_PATH)

// WHEN
postApi.getPostsResponse()

advanceUntilIdle()

val request = mockWebServer.takeRequest()

// THEN
Truth.assertThat(request.path).isEqualTo("/posts")

}
}

结果错误: java.lang.IllegalStateException: This job has not completed yet
如果 launch,则此测试不起作用使用了builder,如果 launch使用了builder,不需要 testCoroutineDispatchertestCoroutineScope ,这是什么原因?正常情况下,即使使用 runBlockingTest,挂起函数也不会在另一个范围内通过。
 @Test
fun `Given we have a valid request, should be done to correct url`() =
runBlockingTest {

// GIVEN
enqueueResponse(200, RESPONSE_JSON_PATH)

// WHEN
launch {
postApi.getPosts()
}

val request = mockWebServer.takeRequest()

// THEN
Truth.assertThat(request.path).isEqualTo("/posts")

}

上面的一个有效。

下面的测试也通过了一些时间。

@测试
好玩 Given api return 200, should have list of posts () =
testCoroutineScope.runBlockingTest {
    // GIVEN
enqueueResponse(200)

// WHEN
var posts: List<Post> = emptyList()
launch {
posts = postApi.getPosts()
}

advanceUntilIdle()

// THEN
Truth.assertThat(posts).isNotNull()
Truth.assertThat(posts.size).isEqualTo(100)

}

我尝试了许多组合调用 posts = postApi.getPosts()没有 launch , 使用 async , 把 enqueueResponse(200)内部异步 async { enqueueResponse(200) }.await()但是测试失败了,有时它通过了,有时它对每个组合都没有。

最佳答案

runBlockTest 存在错误在完成运行测试的协程之前不等待其他线程/作业完成。
我尝试使用 runBlocking成功(我使用了很棒的 Hamcrest 端口到 Kotlin Hamkrest)

fun `run test` = runBlocking {
mockWebServer.enqueue(MockResponse().setResponseCode(200).setBody(""))

// make HTTP call

val result = mockWebServer.takeRequest(2000L, TimeUnit.MILLISECONDS)

assertThat(result != null, equalTo(true))
}
这里有几点需要注意:
  • 使用线程阻塞调用应该从不在没有超时的情况下被调用。总是最好一无所获地失败,然后永远阻塞一个线程。
  • 使用runBlocking可能会被一些人认为是不不不。然而this blog post概述了运行并发代码的不同方法,以及它们的不同用例。我们通常想使用 runBlockingTest或 ( TestCoroutineDispatcher.runBlockingTest ) 以便我们的测试代码和应用程​​序代码同步。通过使用相同的 Dispatcher,我们可以确保所有作业都完成,等等。TestCoroutineDispatcher还具有方便的“时钟”功能,可以使延迟消失。但是,在测试应用程序的 HTTP 层时,如果有一个模拟服务器在单独的线程上运行,我们的同步点是 takeRequest。 .所以我们可以愉快地使用runBlocking允许我们使用协程和在不同线程上运行的模拟服务器一起工作而不会出现任何问题。
  • 关于android - 使用 MockWebServer 暂停功能测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62161708/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com