Skip to content

NPE when using WebTestClient with Spring MVC #9304

Closed
@pkubowicz

Description

@pkubowicz

Describe the bug
According to Spring Framework 5.3 Reference Documentation, I should be able to use WebTestClient to test Spring MVC applications. I tried it and it does not work if you have something reactive on classpath.

Caused by: java.lang.NullPointerException
	at org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers$CsrfMutator.afterConfigurerAdded(SecurityMockServerConfigurers.java:259)
	at org.springframework.test.web.reactive.server.DefaultWebTestClientBuilder.apply(DefaultWebTestClientBuilder.java:247)
	at org.springframework.test.web.reactive.server.DefaultWebTestClient.mutateWith(DefaultWebTestClient.java:160)
	at com.example.mvcwebtestclient.GreetingControllerTest.create(GreetingControllerTest.java:24)

The code in SecurityMockServerConfigurers (spring-security-test 5.4.2) is clearly buggy: it accesses a nullable argument httpHandlerBuilder:

		public void afterConfigurerAdded(WebTestClient.Builder builder,
				@Nullable WebHttpHandlerBuilder httpHandlerBuilder, @Nullable ClientHttpConnector connector) {
			CsrfWebFilter filter = new CsrfWebFilter();
			filter.setRequireCsrfProtectionMatcher((e) -> ServerWebExchangeMatcher.MatchResult.notMatch());
			httpHandlerBuilder.filters((filters) -> filters.add(0, filter));
		}

Sample

build.gradle

dependencies {
	implementation(platform("org.springframework.boot:spring-boot-dependencies:2.4.1"))
	implementation 'org.springframework.boot:spring-boot-starter-data-mongodb-reactive'
	implementation 'org.springframework.boot:spring-boot-starter-security'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.boot:spring-boot-starter-webflux' // result of spring-framework#26308
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testImplementation 'io.projectreactor:reactor-test'
	testImplementation 'org.springframework.security:spring-security-test'
}

GreetingController.java

@RestController
@RequestMapping("/greetings")
public class GreetingController {

    @GetMapping
    public Flux<String> findAll() {
        return Flux.just("Hello", "world!");
    }
}

GreetingControllerTest.java

@SpringBootTest
class GreetingControllerTest {

    private WebTestClient client;

    @Autowired
    public void create(WebApplicationContext context) {
        client = MockMvcWebTestClient.bindToApplicationContext(context)
                .apply(springSecurity())
                .configureClient()
                .build()
                .mutateWith(csrf());
    }

    @Test
    public void findsAll() {
        client.get().uri("/greetings")
                .exchange()
                .expectStatus().isOk();
    }
}

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions