mockJwt() WebTestClientConfigurer with MockMvcWebTestClient throws a NullPointerException.

See original GitHub issue

Describe the bug mockJwt() WebTestClientConfigurer does not seem to work with MockMvcWebTestClient that was introduced in Spring 5.3 as documented.

To Reproduce

	@Test
	void getMessagesWebTestClient() {
		final WebTestClient testClient = MockMvcWebTestClient.bindTo(this.mockMvc)
				.build();
		testClient.mutateWith(mockJwt().authorities(new SimpleGrantedAuthority("SCOPE_message:read")))
				.get()
				.uri("/messages")
				.exchange()
				.expectStatus().isOk()
				.expectBody()
				.jsonPath("$[0]").isEqualTo("hello")
				.jsonPath("$[1]").isEqualTo("world"); ;
	}

throws the exception below

java.lang.NullPointerException: Cannot invoke "org.springframework.web.server.adapter.WebHttpHandlerBuilder.filter(org.springframework.web.server.WebFilter[])" because "httpHandlerBuilder" is null

	at org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers$JwtMutator.afterConfigurerAdded(SecurityMockServerConfigurers.java:540)
	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.demojwttest.MessageControllerTest.getMessagesWebTestClient(MessageControllerTest.java:51)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
	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:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	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:210)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
	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:129)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	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:143)
	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:129)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	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:143)
	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:129)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
	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.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)

while the equivalent following tests work

// MockMvc
	@Test
	void getMessages() throws Exception {
		this.mockMvc.perform(get("/messages")
				.with(jwt().authorities(new SimpleGrantedAuthority("SCOPE_message:read"))))
				.andExpect(status().isOk())
				.andExpect(jsonPath("$[0]").value("hello"))
				.andExpect(jsonPath("$[1]").value("world"));
	}

// @WithMockUser
	@Test
	@WithMockUser(authorities = "SCOPE_message:read")
	void getMessagesWebTestClientWithMockUser() {
		final WebTestClient testClient = MockMvcWebTestClient.bindTo(this.mockMvc)
				.build();
		testClient.get()
				.uri("/messages")
				.exchange()
				.expectStatus().isOk()
				.expectBody()
				.jsonPath("$[0]").isEqualTo("hello")
				.jsonPath("$[1]").isEqualTo("world"); ;
	}

Expected behavior

The first example works

Sample https://github.com/making/spring-security-gh-9257

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:6
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

4reactions
rwinchcommented, May 5, 2022

@gursahibsahni Sorry the workaround I posted previously, should have removed the mutateWith method. I’ve updated the example and provided a link to a repository that demonstrates the workaround in its entirety.

@soasada @membersound I’ve updated the sample above to demonstrate how to workaround CSRF test support not working too.

@rstoyanchev Thanks for the reply. I’d like to figure out a way that Spring Security users can use WebTestClient using the same APIs for WebMvc and WebFlux backends. It is confusing that mutateWith does not work for MockMvc based tests. What’s more is there is currently no way to use many of Spring Security’s test features when WebTestClient + MockMvc.

4reactions
gursahibsahnicommented, Aug 31, 2021

@making Thanks for the report. We will look into a proper solution. In the meantime, you can work around it using:

@Test
	void getMessagesWebTestClient() {
		TestingAuthenticationToken authentication = new TestingAuthenticationToken("a", "b", "SCOPE_message:read");
		TestSecurityContextHolder.setAuthentication(authentication);
		final WebTestClient testClient = MockMvcWebTestClient.bindTo(this.mockMvc)
				.build();
		testClient.mutateWith(mockJwt().authorities(new SimpleGrantedAuthority("SCOPE_message:read")))
				.get()
				.uri("/messages")
				.exchange()
				.expectStatus().isOk()
				.expectBody()
				.jsonPath("$[0]").isEqualTo("hello")
				.jsonPath("$[1]").isEqualTo("world"); ;
	}

This still doesn’t work for me.

Read more comments on GitHub >

github_iconTop Results From Across the Web

WebTestclient is throwing Null Exception tough @Autowire is ...
From how I understand this issue from the Spring Boot project, using @AutoconfigureWebTestClient only works if you are testing a WebFlux ...
Read more >
SecurityMockServerConfigurers (spring-security-docs 6.0.0 API)
This uses a default password of "password" and granted authorities of "ROLE_USER". Returns: the WebTestClientConfigurer to use. mockJwt. public static ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found