Reputation: 11
I'm trying to write test for controller method which requires authenticated user, this how it looks:
@Controller("/api/task")
class TaskController(
private val taskCompletionService: TaskCompletionService,
private val userSecurityService: UserSecurityService
) {
@Post("/{id}")
suspend fun completeTask(
@PathVariable id: Long,
@Body request: TaskCompletionRequestDTO
) {
taskCompletionService.completeTask(
taskId = id,
userId = userSecurityService.getUserId(),
action = request.action
)
}
}
I'm struggling with mocking UserSecurityService
@Singleton
class UserSecurityService {
fun getUserId(): Int = getUserIdOrNull() ?: throw UserIdNotFoundException("UserId not found")
fun getUserIdOrNull(): Int? = getPrincipal()?.attributes?.get(PrincipalAttribute.USER_ID)?.toString()?.toInt()
@OptIn(ExperimentalStdlibApi::class)
private fun getPrincipal(): Authentication? =
(ServerRequestContext.currentRequest<Any?>().get().userPrincipal.getOrNull()) as? Authentication
@OptIn(ExperimentalStdlibApi::class)
fun isAuthorized(): Boolean {
val principal =
ServerRequestContext.currentRequest<HttpRequest<*>>()
.getOrNull()
?.attributes?.get(HttpAttributes.PRINCIPAL.toString(), Authentication::class.java)
return principal != null && !principal.isEmpty
}
}
@Replaces(UserSecurityService::class)
@Bean
fun userSecurityService(): UserSecurityService = mock()
and stubbing
whenever(userSecurityService().getUserId()).thenReturn(123)
, but somehow getUserId()
always returns 0, so I assume that kind of stubbing does not work (
The situation is complicated by the fact that I have several HTTP filters that need to access data about the authenticated user (through UserSecurityService
). In the real application, I use a JWT token, but in the test I'm not able to use the production token
micronaut:
security:
token:
jwt:
claims-validators:
issuer: https://mysecretproject.com/auth
signatures:
secret:
generator:
secret: ${SECURITY_TOKEN}
Ideally, I would like to use something similar to @WithMockUser
in Spring, where I can mock a user authentication without needing a real JWT token. Is there a way in Micronaut to mock the JWT authentication or bypass the token verification in tests?
Thanks in advance for your help!
Upvotes: 0
Views: 47
Reputation: 1839
Not my repository but I successfully implemented that by following this:
https://github.com/lstoeferle/micronaut-jwt-auth-mock
Basically you replace TokenAuthenticationFetcher
with your own, and can hard code the authentication with a user and given roles.
Upvotes: 0