Before Ktor 3.0.0 released, this block of code was...
# ktor
m
Before Ktor 3.0.0 released, this block of code was acceptable:
Copy code
lateinit var server: NettyApplicationEngine


    beforeTest {
        server = embeddedServer(Netty, PORT, module = Application::applicationTestModule).start()
    }

    afterTest {
        server.stop(5, 5)
    }
After upgrading to Ktor 3.0.0 ,
embeddedServer
give me this error: Any idea?
solved 1
a
In Ktor 3.0.0, you can declare the server variable the following way:
Copy code
lateinit var server: EmbeddedServer<NettyApplicationEngine, NettyApplicationEngine.Configuration>
m
Ah ok, thank you!
@Aleksei Tirman [JB] another problem here too:
Copy code
private val engine = TestApplicationEngine(createTestEnvironment())

internal class AuthTokenTest : FunSpec({

    beforeTest {
        engine.start(wait = true)
    }

    test("token bør returnere NAVident") {

        val call =
            engine.handleRequest {
                addHeader(HttpHeaders.Authorization, "Bearer $tokenWithNavIdent")
            }

        val navIdent = AuthToken.getSaksbehandler(call)
        navIdent.ident shouldBe "Z123456"
    }
Could you explain me?
CleanShot 2024-10-14 at 14.14.52.png
o
@mudasar187, try to use
TestApplication()
instead of
TestApplicationEngine(...)
and
application.client.get(...)
to perform requests.
m
CleanShot 2024-10-14 at 14.26.30.png
a
Can you share the code as text?
m
Copy code
private val engine = TestApplicationEngine(createTestEnvironment())

internal class AuthTokenTest : FunSpec({

    beforeTest {
        engine.start(wait = true)
    }

    test("token bør returnere NAVident") {

        val call =
            engine.handleRequest {
                addHeader(HttpHeaders.Authorization, "Bearer $tokenWithNavIdent")
            }

        val navIdent = AuthToken.getSaksbehandler(call)
        navIdent.ident shouldBe "Z123456"
    }
}
a
You can use the following code:
Copy code
val engine = TestApplication {
    // Configure test server here
}
engine.start()

val response = engine.client.get("/") {
    header(HttpHeaders.Authorization, "Bearer $tokenWithNavIdent")
}
val call = response.call
m
my method
getSaksbehandler
takes ApplicationCall as parameter, but now i get HttpClientCall
a
What is the implementation of this method?
m
Copy code
object AuthToken {
    fun getSaksbehandler(call: ApplicationCall): NavIdent {
        val oboToken =
            call.request.headers[HttpHeaders.Authorization]?.removePrefix("Bearer ")
                ?: throw Error("Could not get token from request header")
        val navIdent = getNAVIdentFromToken(oboToken)

        return NavIdent(navIdent)
    }

    private fun getNAVIdentFromToken(token: String): String {
        val decodedJWT = JWT.decode(token)
        return decodedJWT.claims[JWT_CLAIM_NAVIDENT]?.asString()
            ?: throw RuntimeException("Missing NAVident in private claims")
    }
}
Copy code
val request = call.receive<OppdragsRequest>()
            val saksbehandler = getSaksbehandler(call)
a
You'll need to rewrite your code to use the testApplication and receive the JWT in a route handler, so the assertion will be made within the test server module.
m
You mean like this?
Copy code
testApplication {
                application {
                    securityConfig(true, mockAuthConfig())
                    routing {
                        authenticate(true, AUTHENTICATION_NAME) {
                            oppdragsInfoApi(oppdragsInfoService)
                        }
                    }
                }
                val response = client.get("$OPPDRAGSINFO_BASE_API_PATH/faggrupper")
                response.status shouldBe HttpStatusCode.Unauthorized
            }
I was trying to isolate my AuthToken object tests but do i need to have
testApplication
now? 😕
a
The
getSaksbehandler
method can only be called in the server call context, so you need a test server application, which is provided by the
testApplication
.
m
I just made a mock test with
mockk
🙂
Copy code
internal class AuthTokenTest : FunSpec({

    test("token bør returnere NAVident") {

        val call = mockk<ApplicationCall>(relaxed = true)
        every { call.request.headers[HttpHeaders.Authorization] } returns "Bearer $tokenWithNavIdent"

        val result = AuthToken.getSaksbehandler(call)
        result.ident shouldBe "Z123456"
    }
}
Its make me test my AuthToken isolated without spinning up a
testApplication
🙂
Thank you for the help @Aleksei Tirman [JB] @Osip Fatkullin