Having configured oauth2:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: ${keycloak.server-url}/realms/${keycloak.realm}
client:
provider:
keycloak:
issuer-uri: ${keycloak.server-url}/realms/${keycloak.realm}
user-name-attribute: email
registration:
keycloak:
client-id: ${keycloak.client-id}
client-secret: ${keycloak.client-secret}
scope: openid
I wonder how to run a @WebFluxTest
for a controller without having to run an actual keycloak server. The following test runs fine, when I have the local keycloak server running:
@WebFluxTest(TaskController::class)
class TaskControllerTest {
@Autowired
private lateinit var client: WebTestClient
@MockkBean
private lateinit var taskService: TaskServiceImpl
@Test
@WithMockUser(roles = ["user"])
fun getByIds() {
val ids = setOf<Long>(1, 2)
every { taskService.getByIds(ids, any()) } returns flowOf(
TaskWithRating(
Task(
id = 1,
title = "title",
description = "desc"
),
Rating(0, 0),
)
)
client
.get()
.uri { uriBuilder ->
uriBuilder
.path("/tasks/byIds")
.queryParam("ids", ids)
.build()
}
.exchange()
.expectStatus().isOk
.expectBody()
.jsonPath("$.length()").isEqualTo(1)
.jsonPath("$.1.task.id").isEqualTo(1)
}
}
When I stop the local keycloak server, the test fails, because spring tries to read the oauth2 configuration during startup, while creating the ApplicationContext:
Failed to load ApplicationContext
...
Factory method 'clientRegistrationRepository' threw exception; nested exception is java.lang.IllegalArgumentException: Unable to resolve Configuration with the provided Issuer of "https://keycloak.local.com/auth/realms/myrealm"
...
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://keycloak.local.com/auth/realms/myrealm/.well-known/openid-configuration": Connection refused; nested exception is java.net.ConnectException: Connection refused
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:784)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:669)
at org.springframework.security.oauth2.client.registration.ClientRegistrations.lambda$oidc$0(ClientRegistrations.java:156)
at org.springframework.security.oauth2.client.registration.ClientRegistrations.getBuilder(ClientRegistrations.java:209)
... 175 more
Caused by: java.net.ConnectException: Connection refused
The test does not need it, because the user is mocked anyway. So I think of disabling the auth2 configuration in @WebFluxTest
, but I could not find out how and if this is a valid approach?
I tried this.
@WebFluxTest(
controllers = [TaskController::class],
excludeAutoConfiguration = [ReactiveSecurityAutoConfiguration::class],
)
and this
@WebFluxTest(
controllers = [TaskController::class],
excludeAutoConfiguration = [ReactiveOAuth2ClientAutoConfiguration::class],
)
But the error is the same.
Turns out I was on the right path. Both, the oauth2 client and resource server auto configurations must be disabled. This works:
@WebFluxTest(
controllers = [TaskController::class],
excludeAutoConfiguration = [
ReactiveOAuth2ClientAutoConfiguration::class,
ReactiveOAuth2ResourceServerAutoConfiguration::class,
],
)
Note that this bypasses potentially disabled features and hence, for example, requires a csrf()
mutation on the test client:
client
.mutateWith(SecurityMockServerConfigurers.csrf())
An alternative to this would be to configure a test-configuration for the security setup using @Import(TestSecurityConfiguration::class)
.