英文:
Ktor testing routes with 'authenticate(){}'
问题
以下是代码部分的翻译:
fun Application.install() {
routing {
route("point") {
authenticate(AUTH_SESSION) {
post("/test") { testController.test(context) }
}
}
}
}
@Test
fun `test auth route`() = testApplication {
val client = client()
client.post("/point/test")
}
请注意,我已经删除了HTML编码字符("
)并将其替换为普通引号。如果您需要其他内容的翻译,请提供相关文本。
英文:
What is the appropriate way of unit testing such routes?
fun Application.install() {
routing {
route("point") {
authenticate(AUTH_SESSION) {
post("/test") { testController.test(context) }
}
}
}
}
The problem is such routes require auth info. This code results in 401 error:
@Test
fun `test auth route`() = testApplication {
val client = client()
client.post("/point/test")
}
I use GoogleOneTap auth for a mobile application. From GoogleOneTap jwt token I generate User session with a Bearer. That session expires after some time.
So, such a test user requires manual auth each time session expires? If so, it's not appropriate for a CI.
Should I implement a simple auth with user-password and call auth before each call under authenticate(AUTH_SESSION)
?
答案1
得分: 0
这是你要翻译的内容的翻译部分:
Finally, I got it:
1) Read through ktor docs https://ktor.io/docs/testing.html
1) With any auth you have auth route: `post("/auth/myprovider")` which gives you bearer cookie
Your routing:
```kotlin
routing {
// auth route to get a bearer cookie
post("/auth/google") { googleAuthController.signIn(context) }
authenticate(AUTH_SESSION) {
// these routes need auth bearer cookie
post("/my/route/requiring/auth")
}
}
post("/my/route/requiring/auth")
uses authentication, hence all testing requests have to have auth bearer cookie. To get it, create a separate test user with test credentials:
class GoogleAuthController(
private val userDao: UserDao
) {
suspend fun signIn(call: ApplicationCall) {
val token = call.parameters["token"]!!
val userInfo: UserInfo? = verifyTestUsers(token) ?: GoogleAuthVerifier.verify(token)
if (userInfo != null) {
// create user
val userSession = UserSession(
id = userInfo.id,
email = userInfo.email,
name = userInfo.name,
pictureUrl = userInfo.pictureUrl,
locale = userInfo.locale
)
// save user to db
userDao.saveUserInfoGoogleOneTap(userSession)
// set user cookie
call.sessions.set(userSession)
call.respond(HttpStatusCode.OK)
} else {
throw IllegalArgumentException("Invalid token")
}
}
// testUsers: Map<String, UserInfo>;
private fun verifyTestUsers(token: String): UserInfo? = testUsers[token]
}
Basically, this is how you can get a cookie for any of your test users.
Next, to make calls, you need a client:
suspend fun ApplicationTestBuilder.myAuthClient(token: String = testUserToken) = createClient {
install(HttpCookies)
install(ContentNegotiation) {
json(Json {
prettyPrint = true
isLenient = true
ignoreUnknownKeys = true
encodeDefaults = true
})
}
}.also {
it.post("/auth/google") {
parameter("token", token)
}
}
Here on each client creation you call your auth method and get credentials for a test user.
Now you are ready to make authenticated calls:
internal class TestAuth {
@Test
fun `test auth`() = testApplication {
val client = myAuthClient()
// here `client` already has a Bearer cookie
val response = client.post("/my/route/requiring/auth")
assert(response.body<String>().isNotEmpty())
}
}
希望这些翻译对你有所帮助。
英文:
Finally, I got it:
- Read through ktor docs https://ktor.io/docs/testing.html
- With any auth you have auth route:
post("/auth/myprovider")
which gives you bearer cookie
Your routing:
routing {
// auth route to get a bearer cookie
post("/auth/google") { googleAuthController.signIn(context) }
authenticate(AUTH_SESSION) {
// these routes need auth bearer cookie
post("/my/route/requiring/auth")
}
}
post("/my/route/requiring/auth")
uses authentication, hence all testing requests have to have auth bearer cookie. To get it, create a separate test user with test credentials:
class GoogleAuthController(
private val userDao: UserDao
) {
suspend fun signIn(call: ApplicationCall) {
val token = call.parameters["token"]!!
val userInfo: UserInfo? = verifyTestUsers(token) ?: GoogleAuthVerifier.verify(token)
if (userInfo != null) {
// create user
val userSession = UserSession(
id = userInfo.id,
email = userInfo.email,
name = userInfo.name,
pictureUrl = userInfo.pictureUrl,
locale = userInfo.locale
)
// save user to db
userDao.saveUserInfoGoogleOneTap(userSession)
// set user cookie
call.sessions.set(userSession)
call.respond(HttpStatusCode.OK)
} else {
throw IllegalArgumentException("Invalid token")
}
}
// testUsers: Map<String, UserInfo>
private fun verifyTestUsers(token: String): UserInfo? = testUsers[token]
}
Basically, this is how you can get a cookie for any of your test users.
Next, to make calls, you need a client:
suspend fun ApplicationTestBuilder.myAuthClient(token: String = testUserToken) = createClient {
install(HttpCookies)
install(ContentNegotiation) {
json(Json {
prettyPrint = true
isLenient = true
ignoreUnknownKeys = true
encodeDefaults = true
})
}
}.also {
it.post("/auth/google") {
parameter("token", token)
}
}
Here on each client creation you call your auth method and get credentials for a test user.
Now you are ready to make authenticated calls:
internal class TestAuth {
@Test
fun `test auth`() = testApplication {
val client = myAuthClient()
// here `client` already has a Bearer cookie
val response = client.post("/my/route/requiring/auth")
assert(response.body<String>().isNotEmpty())
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论