Ktor 3.0.0 Help

Testing

Ktor provides a MockEngine that simulates HTTP calls without connecting to the endpoint.

Add dependencies

Before using MockEngine, you need to include the ktor-client-mock artifact in the build script.

testImplementation("io.ktor:ktor-client-mock:$ktor_version")
testImplementation "io.ktor:ktor-client-mock:$ktor_version"
<dependency> <groupId>io.ktor</groupId> <artifactId>ktor-client-mock-jvm</artifactId> <version>${ktor_version}</version> </dependency>

Usage

Share client configuration

Let's see how to use MockEngine to test a client. Suppose the client has the following configuration:

  • The CIO engine is used to make requests.

  • The Json plugin is installed to deserialize incoming JSON data.

To test this client, its configuration needs to be shared with a test client, which uses MockEngine. To share a configuration, you can create a client wrapper class that takes an engine as a constructor parameter and contains a client configuration.

@Serializable data class IpResponse(val ip: String) class ApiClient(engine: HttpClientEngine) { private val httpClient = HttpClient(engine) { install(ContentNegotiation) { json() } } suspend fun getIp(): IpResponse = httpClient.get("https://api.ipify.org/?format=json").body() }

Then, you can use the ApiClient as follows to create an HTTP client with the CIO engine and make a request.

fun main() { runBlocking { val client = ApiClient(CIO.create()) val response = client.getIp() println(response.ip) } }

Test a client

To test a client, you need to create a MockEngine instance with a handler that can check request parameters and respond with the required content (a JSON object in our case).

val mockEngine = MockEngine { request -> respond( content = ByteReadChannel("""{"ip":"127.0.0.1"}"""), status = HttpStatusCode.OK, headers = headersOf(HttpHeaders.ContentType, "application/json") ) }

Then, you can pass the created MockEngine to initialize ApiClient and make required assertions.

class ApiClientTest { @Test fun sampleClientTest() { runBlocking { val mockEngine = MockEngine { request -> respond( content = ByteReadChannel("""{"ip":"127.0.0.1"}"""), status = HttpStatusCode.OK, headers = headersOf(HttpHeaders.ContentType, "application/json") ) } val apiClient = ApiClient(mockEngine) Assert.assertEquals("127.0.0.1", apiClient.getIp().ip) } } }

You can find the full example here: client-testing-mock.

Last modified: 19 July 2022