Reputation: 71
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
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
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
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