gpt4 book ai didi

android - 使用 MockWebServer 测试 OkHttp 并使用 Buffer body 测试 MockResponse

转载 作者:搜寻专家 更新时间:2023-11-01 09:26:17 28 4
gpt4 key购买 nike

我正在尝试测试一些涉及 OkHttp3 的下载代码,但不幸失败了。目标:测试 下载图像文件并验证其是否有效。平台:安卓。此代码可在生产环境中运行,但测试代码没有任何意义。

产品代码

class FileDownloaderImpl internal constructor(
private val ioScheduler: Scheduler,
private val logger: LoggingInterceptor,
private val parser: ((String) -> HttpUrl)? // for testing only
) : FileDownloader {

@Inject constructor(logger: LoggingInterceptor) : this(Schedulers.io(), logger, null)

override fun downloadFile(url: String, destination: File): Single<File> {
Logger.d(TAG, "downloadFile\nurl = $url\nfile = $destination")

val client = OkHttpClient.Builder()
.addInterceptor(logger)
.build()

val call = client.newCall(newRequest(url))
return Single.fromCallable { call.execute() }
.doOnDispose { call.cancel() }
.subscribeOn(ioScheduler)
.map { response ->
Logger.d(TAG, "Successfully downloaded board: $response")
return@map response.body()!!.use { body ->
Okio.buffer(Okio.sink(destination)).use { sink ->
sink.writeAll(body.source())
}
destination
}
}
}

/**
* Creates the request, optionally parsing the URL into an [HttpUrl]. The primary (maybe only)
* use-case for that is for wrapping the URL in a `MockWebServer`.
*/
private fun newRequest(url: String): Request {
val httpUrl = parser?.invoke(url)
val builder = Request.Builder()
httpUrl?.let { builder.url(it) } ?: builder.url(url)
return builder.build()
}
}

测试代码(JUnit5)

@ExtendWith(TempDirectory::class)
internal class FileDownloaderImplTest {

private val mockWebServer = MockWebServer()
private val logger = LoggingInterceptor(HttpLoggingInterceptor.Level.BODY) { msg -> println(msg) }
private val fileDownloader = FileDownloaderImpl(Schedulers.trampoline(), logger) {
mockWebServer.url("/$it")
}

@BeforeEach fun setup() {
mockWebServer.start()
}

@AfterEach fun teardown() {
mockWebServer.shutdown()
}

@Test fun downloadFile(@TempDir tempDirectory: Path) {
// Given
val res = javaClass.classLoader.getResource("green20.webp")
val f = File(res.path)
val buffer = Okio.buffer(Okio.source(f)).buffer()
mockWebServer.enqueue(MockResponse().setBody(buffer))
val destFile = tempDirectory.resolve("temp.webp").toFile()

// Verify initial condition
destFile.exists() shouldBe false

// When
fileDownloader.downloadFile("test.html", destFile)

// Then
.test()
.assertValue { file ->
file.exists() shouldBe true
file.length() shouldEqualTo 66 // FAIL: always 0
true
}
}
}

更多细节

“green20.webp”是一个存在于 app/test/resources 中的文件。当我调试时,所有迹象都表明它存在。关于调试,我在产品代码中设置了断点,看起来 Response 对象(可能是 MockResponse)没有主体。我不知道为什么会这样。

当前想法:

  1. 我没有正确添加模拟响应正文
  2. 文件以某种方式“打开”,因此它的长度始终为 0,即使它实际上不是空的。

编辑

我尝试从测试中删除 MockWebServer 并启动真实 下载,我的测试实际上通过了。所以,我认为我对 MockResponse 及其主体做错了什么。任何帮助将不胜感激。

最佳答案

由于我不清楚的原因,Okio.buffer(Okio.source(file)).buffer() 总是返回一个空的 Buffer。然而,以下是有效的:

mockWebServer.enqueue(MockResponse().setBody(Buffer().apply {
writeAll(Okio.source(file))
}))

我现在正在做的是手动创建一个新缓冲区并将整个文件写入其中。现在我的 MockResponse 有了实体。

我仍然希望有人能解释一下这一切的原因....

关于android - 使用 MockWebServer 测试 OkHttp 并使用 Buffer body 测试 MockResponse,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50365266/

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