Skip to content

[Junie]: feat: make client property in ApplicationTestBuilder mutable #4879

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ public final class io/ktor/server/testing/ApplicationTestBuilder : io/ktor/serve
public fun <init> ()V
public fun createClient (Lkotlin/jvm/functions/Function1;)Lio/ktor/client/HttpClient;
public fun getClient ()Lio/ktor/client/HttpClient;
public fun setClient (Lio/ktor/client/HttpClient;)V
public final fun startApplication (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public abstract interface class io/ktor/server/testing/ClientProvider {
public abstract fun createClient (Lkotlin/jvm/functions/Function1;)Lio/ktor/client/HttpClient;
public abstract fun getClient ()Lio/ktor/client/HttpClient;
public abstract fun setClient (Lio/ktor/client/HttpClient;)V
}

public class io/ktor/server/testing/ExpectedTestException : java/lang/Throwable {
Expand All @@ -29,6 +31,7 @@ public final class io/ktor/server/testing/On {
public final class io/ktor/server/testing/TestApplication : io/ktor/server/testing/ClientProvider {
public fun createClient (Lkotlin/jvm/functions/Function1;)Lio/ktor/client/HttpClient;
public fun getClient ()Lio/ktor/client/HttpClient;
public fun setClient (Lio/ktor/client/HttpClient;)V
public final fun start (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun stop (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@

// Library unique name: <io.ktor:ktor-server-test-host>
abstract interface io.ktor.server.testing/ClientProvider { // io.ktor.server.testing/ClientProvider|null[0]
abstract val client // io.ktor.server.testing/ClientProvider.client|{}client[0]
abstract var client // io.ktor.server.testing/ClientProvider.client|{}client[0]
abstract fun <get-client>(): io.ktor.client/HttpClient // io.ktor.server.testing/ClientProvider.client.<get-client>|<get-client>(){}[0]
abstract fun <set-client>(io.ktor.client/HttpClient) // io.ktor.server.testing/ClientProvider.client.<set-client>|<set-client>(io.ktor.client.HttpClient){}[0]

abstract fun createClient(kotlin/Function1<io.ktor.client/HttpClientConfig<out io.ktor.client.engine/HttpClientEngineConfig>, kotlin/Unit>): io.ktor.client/HttpClient // io.ktor.server.testing/ClientProvider.createClient|createClient(kotlin.Function1<io.ktor.client.HttpClientConfig<out|io.ktor.client.engine.HttpClientEngineConfig>,kotlin.Unit>){}[0]
}
Expand Down Expand Up @@ -47,8 +48,9 @@ final class io.ktor.server.testing.client/TestHttpClientEngine : io.ktor.client.
final class io.ktor.server.testing/ApplicationTestBuilder : io.ktor.server.testing/ClientProvider, io.ktor.server.testing/TestApplicationBuilder { // io.ktor.server.testing/ApplicationTestBuilder|null[0]
constructor <init>() // io.ktor.server.testing/ApplicationTestBuilder.<init>|<init>(){}[0]

final val client // io.ktor.server.testing/ApplicationTestBuilder.client|{}client[0]
final var client // io.ktor.server.testing/ApplicationTestBuilder.client|{}client[0]
final fun <get-client>(): io.ktor.client/HttpClient // io.ktor.server.testing/ApplicationTestBuilder.client.<get-client>|<get-client>(){}[0]
final fun <set-client>(io.ktor.client/HttpClient) // io.ktor.server.testing/ApplicationTestBuilder.client.<set-client>|<set-client>(io.ktor.client.HttpClient){}[0]

final fun createClient(kotlin/Function1<io.ktor.client/HttpClientConfig<out io.ktor.client.engine/HttpClientEngineConfig>, kotlin/Unit>): io.ktor.client/HttpClient // io.ktor.server.testing/ApplicationTestBuilder.createClient|createClient(kotlin.Function1<io.ktor.client.HttpClientConfig<out|io.ktor.client.engine.HttpClientEngineConfig>,kotlin.Unit>){}[0]
final suspend fun startApplication() // io.ktor.server.testing/ApplicationTestBuilder.startApplication|startApplication(){}[0]
Expand All @@ -59,8 +61,9 @@ final class io.ktor.server.testing/ExternalServicesBuilder { // io.ktor.server.t
}

final class io.ktor.server.testing/TestApplication : io.ktor.server.testing/ClientProvider { // io.ktor.server.testing/TestApplication|null[0]
final val client // io.ktor.server.testing/TestApplication.client|{}client[0]
final var client // io.ktor.server.testing/TestApplication.client|{}client[0]
final fun <get-client>(): io.ktor.client/HttpClient // io.ktor.server.testing/TestApplication.client.<get-client>|<get-client>(){}[0]
final fun <set-client>(io.ktor.client/HttpClient) // io.ktor.server.testing/TestApplication.client.<set-client>|<set-client>(io.ktor.client.HttpClient){}[0]

final fun createClient(kotlin/Function1<io.ktor.client/HttpClientConfig<out io.ktor.client.engine/HttpClientEngineConfig>, kotlin/Unit>): io.ktor.client/HttpClient // io.ktor.server.testing/TestApplication.createClient|createClient(kotlin.Function1<io.ktor.client.HttpClientConfig<out|io.ktor.client.engine.HttpClientEngineConfig>,kotlin.Unit>){}[0]
final suspend fun start() // io.ktor.server.testing/TestApplication.start|start(){}[0]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,14 @@ import kotlin.coroutines.EmptyCoroutineContext
@KtorDsl
public interface ClientProvider {
/**
* Returns a client with the default configuration.
* A client with the default configuration.
* This property is mutable, so you can set your own configured client instance.
*
* [Report a problem](https://ktor.io/feedback/?fqname=io.ktor.server.testing.ClientProvider.client)
*
* @see [testApplication]
*/
public val client: HttpClient
public var client: HttpClient
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep val here, but make it var in TestApplicationBuilder

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


/**
* Creates a client with a custom configuration.
Expand Down Expand Up @@ -360,7 +361,17 @@ public open class TestApplicationBuilder {
@KtorDsl
public class ApplicationTestBuilder : TestApplicationBuilder(), ClientProvider {

override val client: HttpClient by lazy { createClient { } }
private var _client: HttpClient? = null
override var client: HttpClient
get() {
if (_client == null) {
_client = createClient { }
}
return _client!!
}
set(value) {
_client = value
}

internal val application: TestApplication by lazy {
TestApplication(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2014-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.tests.server.testing

import io.ktor.client.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.testing.*
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotSame

class ClientConfigurationTest {

@Test
fun testClientConfiguration() = testApplication {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have TestApplicationTest. Move this test into it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Set up a simple route
application {
routing {
get("/hello") {
call.respondText("Hello, World!")
}
}
}

// Store the original client
val originalClient = client

// Create a new client
val configuredClient = createClient { }

// Set the new client as the default
client = configuredClient
Comment on lines +35 to +39
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's simplify this

Suggested change
// Create a new client
val configuredClient = createClient { }
// Set the new client as the default
client = configuredClient
// Create a new client and set it as the default
client = createClient { }


// Verify that the client has been changed
assertNotSame(originalClient, client)

// Test the configured client
val response = client.get("/hello")
assertEquals(HttpStatusCode.OK, response.status)
assertEquals("Hello, World!", response.bodyAsText())
}
}
Loading