Scrobot
Scrobot

Reputation: 1981

Spring boot with WebFlux always throw 403 status in tests

Great thx for viewing my question) I have some strange subject: my spring boot tests don't work. They start successfully but always throwing 403 HTTP status when making the requests to any controller I have some project with next dependencies:

buildscript {
    ext.kotlin_version = '1.3.71'

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.71"
        classpath "org.springframework.boot:spring-boot-gradle-plugin:2.2.1.RELEASE"
        classpath "com.google.cloud.tools.jib:com.google.cloud.tools.jib.gradle.plugin:1.8.0"
    }
}

plugins {
    id "org.springframework.boot" version "2.2.5.RELEASE"
    id "io.spring.dependency-management" version "1.0.9.RELEASE"
    id "com.google.cloud.tools.jib" version "1.8.0"
    id "org.jetbrains.kotlin.jvm" version "1.3.71"
    id "org.jetbrains.kotlin.plugin.spring" version "1.3.71"
    id "org.jetbrains.kotlin.plugin.jpa" version "1.3.71"
}

apply plugin: 'kotlin'

configurations {
    developmentOnly
    runtimeClasspath {
        extendsFrom developmentOnly
    }
}

repositories {
    maven {
        url "https://plugins.gradle.org/m2/"
    }
    maven {
        url "http://oss.jfrog.org/artifactory/oss-snapshot-local/"
    }
    mavenCentral()
}

kotlin {
    sourceSets {
        main.kotlin.srcDirs += 'src/main/myKotlin'
    }
}

dependencies {
    implementation "joda-time:joda-time:2.10.5"
    implementation "org.springframework.boot:spring-boot-starter-security"
    implementation "org.springframework.boot:spring-boot-starter-actuator"
    implementation "org.springframework.boot:spring-boot-starter-batch"
    implementation "org.springframework.boot:spring-boot-starter-jdbc"
    implementation "org.springframework.boot:spring-boot-starter-data-jpa"
    implementation "org.springframework.boot:spring-boot-starter-data-mongodb-reactive"
    implementation "org.springframework.boot:spring-boot-starter-mail"
    implementation "org.springframework.boot:spring-boot-starter-quartz"
    implementation "org.springframework.boot:spring-boot-starter-webflux"
    implementation "com.fasterxml.jackson.module:jackson-module-kotlin"
    implementation "io.springfox:springfox-swagger2:3.0.0-SNAPSHOT"
    implementation "io.springfox:springfox-swagger-ui:3.0.0-SNAPSHOT"
    implementation "io.springfox:springfox-spring-webflux:3.0.0-SNAPSHOT"
    implementation "org.flywaydb:flyway-core"
    implementation "org.jetbrains.kotlin:kotlin-reflect"
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-reactor"
    developmentOnly "org.springframework.boot:spring-boot-devtools"
    runtimeOnly "org.postgresql:postgresql"
    testImplementation("org.springframework.boot:spring-boot-starter-test") {
        exclude group: "org.junit.vintage", module: "junit-vintage-engine"
    }
    testImplementation("de.flapdoodle.embed:de.flapdoodle.embed.mongo")
    testImplementation("io.projectreactor:reactor-test")
    testImplementation("org.springframework.batch:spring-batch-test")
    testImplementation("com.ninja-squad:springmockk:2.0.0")
    testImplementation('com.h2database:h2')
}

test {
    useJUnitPlatform()
}

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
    kotlinOptions {
        freeCompilerArgs = ["-Xjsr305=strict"]
        jvmTarget = "1.8"
    }
}

I implemented some functionality, and then I began coverage it with tests. But, then I start them, spring always throws exception with 403 response status. Here is the reports:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.5.RELEASE)

2020-03-26 11:24:23.345  INFO 38406 --- [    Test worker] r.m.b.web.signin.SignInControllerTest    : Starting SignInControllerTest on MacBook-Pro-Apple with PID 38406 (started by alexscrobot in /Users/alexscrobot/development/backends/medissima)
2020-03-26 11:24:23.347  INFO 38406 --- [    Test worker] r.m.b.web.signin.SignInControllerTest    : No active profile set, falling back to default profiles: default
2020-03-26 11:24:26.418  INFO 38406 --- [    Test worker] ctiveUserDetailsServiceAutoConfiguration : 

Using generated security password: 499ec504-7b25-484f-87b3-d6b6d2f7cc06

2020-03-26 11:24:26.553 DEBUG 38406 --- [    Test worker] s.w.r.r.m.a.RequestMappingHandlerMapping : 1 mappings in 'requestMappingHandlerMapping'
2020-03-26 11:24:26.671 DEBUG 38406 --- [    Test worker] o.s.w.r.handler.SimpleUrlHandlerMapping  : Patterns [/swagger-ui.html**, /webjars/**] in 'resourceHandlerMapping'
2020-03-26 11:24:26.765 DEBUG 38406 --- [    Test worker] o.s.w.r.r.m.a.ControllerMethodResolver   : ControllerAdvice beans: none
2020-03-26 11:24:27.338 DEBUG 38406 --- [    Test worker] o.s.w.s.adapter.HttpWebHandlerAdapter    : enableLoggingRequestDetails='false': form data and headers will be masked to prevent unsafe logging of potentially sensitive data
2020-03-26 11:24:27.390  INFO 38406 --- [    Test worker] r.m.b.web.signin.SignInControllerTest    : Started SignInControllerTest in 4.384 seconds (JVM running for 6.038)
2020-03-26 11:24:28.628 DEBUG 38406 --- [    Test worker] o.s.w.r.f.client.ExchangeFunctions       : [48fcb68c] HTTP POST /api/sign-in
2020-03-26 11:24:28.759 DEBUG 38406 --- [     parallel-1] o.s.http.codec.json.Jackson2JsonEncoder  : [48fcb68c] Encoding [RequestCredentials([email protected], password=123456)]
2020-03-26 11:24:28.797 DEBUG 38406 --- [     parallel-1] o.s.w.s.adapter.HttpWebHandlerAdapter    : [6997f224] HTTP POST "/api/sign-in"
2020-03-26 11:24:28.911 DEBUG 38406 --- [oundedElastic-1] o.s.w.s.s.DefaultWebSessionManager       : Created new WebSession.
2020-03-26 11:24:28.926 DEBUG 38406 --- [oundedElastic-1] o.s.w.s.adapter.HttpWebHandlerAdapter    : [6997f224] Completed 403 FORBIDDEN
2020-03-26 11:24:28.930 DEBUG 38406 --- [oundedElastic-1] o.s.w.r.f.client.ExchangeFunctions       : [48fcb68c] Response 403 FORBIDDEN

Status expected:<200 OK> but was:<403 FORBIDDEN>

> POST /api/sign-in
> WebTestClient-Request-Id: [1]
> Accept: [application/json]
> Content-Type: [application/json]
> Content-Length: [45]

{"email":"[email protected]","password":"123456"}

< 403 FORBIDDEN Forbidden
< Content-Type: [text/plain]
< Cache-Control: [no-cache, no-store, max-age=0, must-revalidate]
< Pragma: [no-cache]
< Expires: [0]
< X-Content-Type-Options: [nosniff]
< X-Frame-Options: [DENY]
< X-XSS-Protection: [1 ; mode=block]
< Referrer-Policy: [no-referrer]

CSRF Token has been associated to this client

java.lang.AssertionError: Status expected:<200 OK> but was:<403 FORBIDDEN>

> POST /api/sign-in
> WebTestClient-Request-Id: [1]
> Accept: [application/json]
> Content-Type: [application/json]
> Content-Length: [45]

{"email":"[email protected]","password":"123456"}

< 403 FORBIDDEN Forbidden
< Content-Type: [text/plain]
< Cache-Control: [no-cache, no-store, max-age=0, must-revalidate]
< Pragma: [no-cache]
< Expires: [0]
< X-Content-Type-Options: [nosniff]
< X-Frame-Options: [DENY]
< X-XSS-Protection: [1 ; mode=block]
< Referrer-Policy: [no-referrer]

CSRF Token has been associated to this client

    at org.springframework.test.web.reactive.server.ExchangeResult.assertWithDiagnostics(ExchangeResult.java:209)
    at org.springframework.test.web.reactive.server.StatusAssertions.assertStatusAndReturn(StatusAssertions.java:227)
    at org.springframework.test.web.reactive.server.StatusAssertions.isOk(StatusAssertions.java:67)
    at ru.medissima.backend.web.signin.SignInControllerTest.success authentication(SignInControllerTest.kt:80)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:675)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:125)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:132)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:124)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:74)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:104)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:62)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:43)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:35)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:202)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:198)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:69)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    at com.sun.proxy.$Proxy2.stop(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:132)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
    at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:412)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
    at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.AssertionError: Status expected:<200 OK> but was:<403 FORBIDDEN>
    at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:59)
    at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:122)
    at org.springframework.test.web.reactive.server.StatusAssertions.lambda$assertStatusAndReturn$4(StatusAssertions.java:227)
    at org.springframework.test.web.reactive.server.ExchangeResult.assertWithDiagnostics(ExchangeResult.java:206)
    ... 91 more

2020-03-26 11:24:28.990 DEBUG 38406 --- [    Test worker] o.s.w.r.f.client.ExchangeFunctions       : [5ee937d3] HTTP POST /api/sign-in
2020-03-26 11:24:28.991 DEBUG 38406 --- [     parallel-2] o.s.w.s.adapter.HttpWebHandlerAdapter    : [5fe66132] HTTP POST "/api/sign-in"
2020-03-26 11:24:28.992 DEBUG 38406 --- [oundedElastic-1] o.s.w.s.s.DefaultWebSessionManager       : Created new WebSession.
2020-03-26 11:24:28.994 DEBUG 38406 --- [oundedElastic-1] o.s.w.s.adapter.HttpWebHandlerAdapter    : [5fe66132] Completed 403 FORBIDDEN
2020-03-26 11:24:28.994 DEBUG 38406 --- [oundedElastic-1] o.s.w.r.f.client.ExchangeFunctions       : [5ee937d3] Response 403 FORBIDDEN
SignInControllerTest > success authentication() FAILED
    java.lang.AssertionError at SignInControllerTest.kt:80
        Caused by: java.lang.AssertionError at SignInControllerTest.kt:80
2 tests completed, 1 failed

Here is the code of test implementation

@RunWith(value = SpringRunner::class)
@WebFluxTest(value = [SignInController::class])
class SignInControllerTest(
    @Autowired val webTestClient: WebTestClient
) {

    @MockkBean
    private lateinit var service: AuthorizationService

    @MockkBean
    private lateinit var validationService: ValidationService

    @MockkBean
    private lateinit var repository: AuthRepository

    @Test
    fun `failed sign in test`() {
        webTestClient
            .post()
            .uri("/api/sign-in")
            .accept(MediaType.APPLICATION_JSON)
            .exchange()
            .expectStatus().isForbidden
    }

    @Test
    fun `success authentication`() {
        val user = createTestUser()

        val request = RequestCredentials(
            "[email protected]",
            "123456"
        )

        val response = Mono.just(user)

        every { repository.findByEmail("") }.returns(Optional.of(user))
        every { validationService.matchPasswords("", "") }.returns(Unit)
        every { service.authorize("", "") } returns response

        webTestClient
            .post()
            .uri("/api/sign-in")
            .bodyValue(request)
            .accept(MediaType.APPLICATION_JSON)
            .exchange()
            .expectStatus().isOk
    }
}

I saw, that csrf token required, but i tried to tuned configuration like this:

@Configuration
class SecurityConfiguration {

    @Bean
    fun springWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
        return http
            .csrf().disable()
            .authorizeExchange()
            .pathMatchers("/api/**").permitAll()
            .anyExchange().permitAll()
            .and()
            .httpBasic()
            .and()
            .build()
    }
}

It's didn't work. Please, help me to understand why test environment not started correctly.

Upvotes: 9

Views: 7700

Answers (2)

Sanjay Bharwani
Sanjay Bharwani

Reputation: 4769

This situation gave me a tough time as well. So the summary of the issue is that the tests are not able to understand the Security config defined for your application. Security config needs to be imported in the test for working.

MySecurityConfig in application defined as a bean

@Configuration
@EnableWebFluxSecurity
public class MySecurityConfig {
  @Bean
  public SecurityWebFilterChain securityWebFilterChain(final ServerHttpSecurity http) {
    http.oauth2Client();
    return http.authorizeExchange().anyExchange().permitAll().and().csrf().disable().build();
  }
}

My Flux controller is a simple controller, which talks to a service which returns Mono and controller maps that Mono to a wrapper response object.

Below two lines goes on your test class. So this will launch WebFluxTest with the dependencies required for YourController And we are also importing the security config defined in MySecurityConfig

@WebFluxTest(value = YourController.class)
@Import(MySecurityConfig.class)

Here is snippet of the test class

@WebFluxTest(value = YourController.class)
@Import(MySecurityConfig.class)
class YourControllerUnitTest {

    @MockBean //mock bean will be inject here
    private YourService yourService ;

    @Autowired
    private WebTestClient webTestClient;

    @SneakyThrows
    @DisplayName("get success response")
    @Test
    void getSuccessResponse() {
       when(yourService.getData(any(YourRequestObject.class))).thenReturn(Mono.just(someMockResponseHere));
        
        webTestClient.post().uri("/getData")
                .bodyValue(requestJSON)
                .header(CONTENT_TYPE, APPLICATION_JSON_VALUE)
                .exchange()
                .expectStatus().isOk()
                .expectBody()
                .jsonPath("$").isNotEmpty()
.jsonPath("$.result[0].name").isEqualTo("test")

this way the WebFlux controller can be tested in Isolation by mocking the downstream communication. You are still launching the context and accessing the API exposed by WebFlux Controller.

Upvotes: 0

Viswanath
Viswanath

Reputation: 1551

It's because you are making a POST request for which CSRF Protection is enabled. This is also the case for PUT requests. There's an open issue regarding this behaviour. For now, as a work-around, just modify your test code as shown below to get past the 403 response

webClient.mutateWith(csrf()).post()

Upvotes: 6

Related Questions