Ktor exposes a MockEngine
for the HttpClient. This engine allows to simulate HTTP calls without
actually connecting to the endpoint. It allows to set a code block, that can handle the request,
and generates a response.
io.ktor.client.engine.mock.MockEngine
in the artifact io.ktor:ktor-client-mock:$ktor_version,io.ktor:ktor-client-mock-jvm:$ktor_version,io.ktor:ktor-client-mock-js:$ktor_version,io.ktor:ktor-client-mock-native:$ktor_version
.
dependencies {
api "io.ktor:ktor-client-mock:$ktor_version"
api "io.ktor:ktor-client-mock-jvm:$ktor_version"
api "io.ktor:ktor-client-mock-js:$ktor_version"
api "io.ktor:ktor-client-mock-native:$ktor_version"
}
dependencies {
testCompile("io.ktor:ktor-client-mock:$ktor_version,io.ktor:ktor-client-mock-jvm:$ktor_version,io.ktor:ktor-client-mock-js:$ktor_version,io.ktor:ktor-client-mock-native:$ktor_version")
}
<project>
...
<dependencies>
<dependency>
<groupId>io.ktor</groupId>
<artifactId>ktor-client-mock</artifactId>
<version>${ktor.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ktor</groupId>
<artifactId>ktor-client-mock</artifactId>
<version>${ktor.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ktor</groupId>
<artifactId>ktor-client-mock</artifactId>
<version>${ktor.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ktor</groupId>
<artifactId>ktor-client-mock</artifactId>
<version>${ktor.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
The usage is very simple: the MockEngine class has a operator invoke
method,
that receives a block/callback that will handle the request. This callback receives an HttpRequest
as this, a HttpClientCall
as a parameter,
and must return a MockHttpResponse
. The MockHttpResponse, includes the HTTP Status Code, a ByteReadChannel with the body, and a set of headers.
A sample illustrating this:
val httpMockEngine = MockEngine { call -> // this: HttpRequest, call: HttpClientCall
when (url.fullUrl) {
"https://example.org/" -> {
MockHttpResponse(
call,
HttpStatusCode.OK,
ByteReadChannel("Hello World!".toByteArray(Charsets.UTF_8)),
headersOf("Content-Type" to listOf(ContentType.Text.Plain.toString()))
)
}
else -> {
error("Unhandled ${url.fullUrl}")
}
}
}
val client = HttpClient(httpMockEngine)
private val Url.hostWithPortIfRequired: String get() = if (port == protocol.defaultPort) host else hostWithPort
private val Url.fullUrl: String get() = "${protocol.name}://$hostWithPortIfRequired$fullPath"