Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/209.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 使用MockWebServer测试OkHttp,使用缓冲区主体测试MockResponse_Android_Unit Testing_Rx Java2_Okhttp_Okio - Fatal编程技术网

Android 使用MockWebServer测试OkHttp,使用缓冲区主体测试MockResponse

Android 使用MockWebServer测试OkHttp,使用缓冲区主体测试MockResponse,android,unit-testing,rx-java2,okhttp,okio,Android,Unit Testing,Rx Java2,Okhttp,Okio,我试图测试一些涉及OkHttp3的下载代码,但失败得很惨。目标:测试下载图像文件并验证其是否有效。平台:安卓。这段代码正在生产中运行,但测试代码毫无意义 产品代码 class FileDownloaderImpl internal constructor( private val ioScheduler: Scheduler, private val logger: LoggingInterceptor, private val parser: ((String) -&g

我试图测试一些涉及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()
    }
}
更多细节

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

当前想法:

  • 我没有正确添加模拟响应主体
  • 文件以某种方式处于“打开”状态,因此其长度始终为0,即使它实际上不是空的
  • 编辑


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

    由于我不清楚的原因,
    Okio.buffer(Okio.source(file)).buffer()
    总是返回一个空的
    缓冲区。但是,以下方法可行:

    mockWebServer.enqueue(MockResponse().setBody(Buffer().apply {
        writeAll(Okio.source(file))
    }))
    
    我现在要做的是手动创建一个新的缓冲区,并将整个文件写入其中。现在我的
    MockResponse
    有了一个真实的身体

    我仍然希望有人能解释一下原因……

    BufferedSource
    上的
    buffer()
    方法没有将整个流读入该缓冲区以返回它。相反,它只允许您访问它从文件中预加载的字节,这些字节将在下次读取时返回

    这是将文件加载到缓冲区的代码:

    val buffer = Buffer()
    file.source().use {
      buffer.writeAll(it)
    }
    

    看起来您的代码和我的最终代码之间的显著区别在于,在将源代码写入缓冲区后,您正在关闭源代码(通过
    使用
    )。我想我天真地希望Okio.source(文件)和writell能够处理这个问题。请确认我现在的理解是正确的?
    val buffer = Buffer()
    file.source().use {
      buffer.writeAll(it)
    }