Tyler Durden
Tyler Durden

Reputation: 71

How to create an HttpResponse object with dummy values in ktor Kotlin?

I am using ktor for developing a microservice in Kotlin. For testing a method, I need to create a dummy HttpResponse (io.ktor.client.statement.HttpResponse to be specific) object with status = 200 and body = some json data.
Any idea how I can create it?

Upvotes: 2

Views: 4668

Answers (3)

Alexey Soshin
Alexey Soshin

Reputation: 17721

With Ktor 2, it's best to use externalServices block instead of attempting to mock HttpResponse. That way you don't need to attempt and mock the internals of Ktor, and it's not complicated at all.

externalServices {
    hosts("https://your-fake-host") {
        routing {
            get("/api/v1/something/{id}/") {
                call.respondText(
                    "{}",
                    contentType = ContentType.Application.Json,
                    status = HttpStatusCode.OK
                )
            }
        }
    }
}

This need to be wrapped with testApplication

Upvotes: 2

ino
ino

Reputation: 1125

I did this with following. I only needed to pass a status code and description, so I didn't bother about other fields.

class CustomHttpResponse(
    private val statusCode: Int,
    private val description: String
) :
    HttpResponse() {
    @InternalAPI
    override val content: ByteReadChannel
        get() = ByteReadChannel("")

    override val call: HttpClientCall
        get() = HttpClientCall(HttpClient())

    override val coroutineContext: CoroutineContext
        get() = EmptyCoroutineContext

    override val headers: Headers
        get() = Headers.Empty

    override val requestTime: GMTDate
        get() = GMTDate()

    override val responseTime: GMTDate
        get() = GMTDate()

    override val status: HttpStatusCode
        get() = HttpStatusCode(statusCode, description)

    override val version: HttpProtocolVersion
        get() = HttpProtocolVersion(name = "HTTP", major = 1, minor = 1)}

Upvotes: 2

Aleksei Tirman
Aleksei Tirman

Reputation: 7079

You can use mockk or a similar kind of library to mock an HttpResponse. Unfortunately, this is complicated because HttpRequest, HttpResponse, and HttpClient objects are tightly coupled with the HttpClientCall. Here is an example of how you can do that:

val call = mockk<HttpClientCall> {
    every { client } returns mockk {}
    coEvery { receive(io.ktor.util.reflect.typeInfo<String>()) } returns "body"
    every { coroutineContext } returns EmptyCoroutineContext
    every { attributes } returns Attributes()
    every { request } returns object : HttpRequest {
        override val call: HttpClientCall = this@mockk
        override val attributes: Attributes = Attributes()
        override val content: OutgoingContent = object : OutgoingContent.NoContent() {}
        override val headers: Headers = Headers.Empty
        override val method: HttpMethod = HttpMethod.Get
        override val url: Url = Url("/")
    }

    every { response } returns object : HttpResponse() {
        override val call: HttpClientCall = this@mockk
        override val content: ByteReadChannel = ByteReadChannel("body")
        override val coroutineContext: CoroutineContext = EmptyCoroutineContext
        override val headers: Headers = Headers.Empty
        override val requestTime: GMTDate = GMTDate.START
        override val responseTime: GMTDate = GMTDate.START
        override val status: HttpStatusCode = HttpStatusCode.OK
        override val version: HttpProtocolVersion = HttpProtocolVersion.HTTP_1_1
    }
}

val response = call.response

Upvotes: 2

Related Questions