Skip to content

Commit af7fe01

Browse files
committed
MockMvcHttpConnector supports RequestPostProcessor's
Closes gh-31298
1 parent 0f6b018 commit af7fe01

File tree

5 files changed

+121
-18
lines changed

5 files changed

+121
-18
lines changed

spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClientBuilder.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -80,7 +80,7 @@ class DefaultWebTestClientBuilder implements WebTestClient.Builder {
8080
private final WebHttpHandlerBuilder httpHandlerBuilder;
8181

8282
@Nullable
83-
private final ClientHttpConnector connector;
83+
private ClientHttpConnector connector;
8484

8585
@Nullable
8686
private String baseUrl;
@@ -277,6 +277,12 @@ public WebTestClient.Builder responseTimeout(Duration timeout) {
277277
return this;
278278
}
279279

280+
@Override
281+
public WebTestClient.Builder clientConnector(ClientHttpConnector connector) {
282+
this.connector = connector;
283+
return this;
284+
}
285+
280286
@Override
281287
public WebTestClient build() {
282288
ClientHttpConnector connectorToUse = this.connector;

spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,18 @@ interface Builder {
512512
*/
513513
Builder responseTimeout(Duration timeout);
514514

515+
/**
516+
* Set the {@link ClientHttpConnector} to use.
517+
* <p>By default, this is initialized and set internally. However, the
518+
* connector may also be prepared externally and passed via
519+
* {@link WebTestClient#bindToServer(ClientHttpConnector)} such as for
520+
* {@code MockMvcWebTestClient} tests, and in that case you can use this
521+
* from {@link #mutateWith(WebTestClientConfigurer)} to replace it.
522+
* @param connector the connector to use
523+
* @since 6.1
524+
*/
525+
Builder clientConnector(ClientHttpConnector connector);
526+
515527
/**
516528
* Apply the given configurer to this builder instance.
517529
* <p>This can be useful for applying pre-packaged customizations.

spring-test/src/main/java/org/springframework/test/web/servlet/client/MockMvcHttpConnector.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.io.StringWriter;
2020
import java.net.URI;
2121
import java.time.Duration;
22+
import java.util.ArrayList;
2223
import java.util.Collections;
2324
import java.util.List;
2425
import java.util.concurrent.atomic.AtomicReference;
@@ -56,6 +57,7 @@
5657
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
5758
import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder;
5859
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
60+
import org.springframework.test.web.servlet.request.RequestPostProcessor;
5961
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
6062
import org.springframework.util.Assert;
6163
import org.springframework.util.ObjectUtils;
@@ -82,9 +84,16 @@ public class MockMvcHttpConnector implements ClientHttpConnector {
8284

8385
private final MockMvc mockMvc;
8486

87+
private final List<RequestPostProcessor> requestPostProcessors;
88+
8589

8690
public MockMvcHttpConnector(MockMvc mockMvc) {
91+
this(mockMvc, Collections.emptyList());
92+
}
93+
94+
private MockMvcHttpConnector(MockMvc mockMvc, List<RequestPostProcessor> requestPostProcessors) {
8795
this.mockMvc = mockMvc;
96+
this.requestPostProcessors = new ArrayList<>(requestPostProcessors);
8897
}
8998

9099

@@ -135,6 +144,8 @@ private RequestBuilder adaptRequest(
135144
}
136145
}
137146

147+
this.requestPostProcessors.forEach(requestBuilder::with);
148+
138149
return requestBuilder;
139150
}
140151

@@ -207,6 +218,15 @@ private MockClientHttpResponse adaptResponse(MvcResult mvcResult) {
207218
return clientResponse;
208219
}
209220

221+
/**
222+
* Create a new instance that applies the given {@link RequestPostProcessor}s
223+
* to performed requests.
224+
* @since 6.1
225+
*/
226+
public MockMvcHttpConnector with(List<RequestPostProcessor> postProcessors) {
227+
return new MockMvcHttpConnector(this.mockMvc, postProcessors);
228+
}
229+
210230

211231
private static class MockMvcServerClientHttpResponse
212232
extends MockClientHttpResponse implements MockServerClientHttpResponse {

spring-test/src/test/java/org/springframework/test/web/servlet/samples/client/standalone/FrameworkExtensionTests.java

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,17 @@
1717
package org.springframework.test.web.servlet.samples.client.standalone;
1818

1919
import java.security.Principal;
20+
import java.util.List;
2021

2122
import org.junit.jupiter.api.Test;
2223

24+
import org.springframework.http.HttpHeaders;
25+
import org.springframework.http.client.reactive.ClientHttpConnector;
26+
import org.springframework.mock.web.MockHttpServletRequest;
2327
import org.springframework.stereotype.Controller;
2428
import org.springframework.test.web.reactive.server.WebTestClient;
29+
import org.springframework.test.web.reactive.server.WebTestClientConfigurer;
30+
import org.springframework.test.web.servlet.client.MockMvcHttpConnector;
2531
import org.springframework.test.web.servlet.client.MockMvcWebTestClient;
2632
import org.springframework.test.web.servlet.request.RequestPostProcessor;
2733
import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder;
@@ -30,6 +36,7 @@
3036
import org.springframework.web.bind.annotation.RequestMapping;
3137
import org.springframework.web.bind.annotation.ResponseBody;
3238
import org.springframework.web.context.WebApplicationContext;
39+
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
3340

3441
import static org.mockito.Mockito.mock;
3542
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -50,16 +57,16 @@ public class FrameworkExtensionTests {
5057

5158
@Test
5259
public void fooHeader() {
53-
this.client.get().uri("/")
54-
.header("Foo", "a=b")
60+
this.client.mutateWith(headers().foo("a=b"))
61+
.get().uri("/")
5562
.exchange()
5663
.expectBody(String.class).isEqualTo("Foo");
5764
}
5865

5966
@Test
6067
public void barHeader() {
61-
this.client.get().uri("/")
62-
.header("Bar", "a=b")
68+
this.client.mutateWith(headers().bar("a=b"))
69+
.get().uri("/")
6370
.exchange()
6471
.expectBody(String.class).isEqualTo("Bar");
6572
}
@@ -68,6 +75,68 @@ private static TestMockMvcConfigurer defaultSetup() {
6875
return new TestMockMvcConfigurer();
6976
}
7077

78+
private static TestWebTestClientConfigurer headers() {
79+
return new TestWebTestClientConfigurer();
80+
}
81+
82+
83+
/**
84+
* Test WebTestClientConfigurer that re-creates the MockMvcHttpConnector
85+
* with a {@code TestRequestPostProcessor}.
86+
*/
87+
private static class TestWebTestClientConfigurer implements WebTestClientConfigurer {
88+
89+
private final TestRequestPostProcessor requestPostProcessor = new TestRequestPostProcessor();
90+
91+
public TestWebTestClientConfigurer foo(String value) {
92+
this.requestPostProcessor.foo(value);
93+
return this;
94+
}
95+
96+
public TestWebTestClientConfigurer bar(String value) {
97+
this.requestPostProcessor.bar(value);
98+
return this;
99+
}
100+
101+
@Override
102+
public void afterConfigurerAdded(
103+
WebTestClient.Builder builder, WebHttpHandlerBuilder httpHandlerBuilder,
104+
ClientHttpConnector connector) {
105+
106+
if (connector instanceof MockMvcHttpConnector mockMvcConnector) {
107+
builder.clientConnector(mockMvcConnector.with(List.of(this.requestPostProcessor)));
108+
}
109+
}
110+
}
111+
112+
113+
/**
114+
* Test {@code RequestPostProcessor} for custom headers.
115+
*/
116+
private static class TestRequestPostProcessor implements RequestPostProcessor {
117+
118+
private final HttpHeaders headers = new HttpHeaders();
119+
120+
121+
public TestRequestPostProcessor foo(String value) {
122+
this.headers.add("Foo", value);
123+
return this;
124+
}
125+
126+
public TestRequestPostProcessor bar(String value) {
127+
this.headers.add("Bar", value);
128+
return this;
129+
}
130+
131+
@Override
132+
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
133+
for (String headerName : this.headers.keySet()) {
134+
request.addHeader(headerName, this.headers.get(headerName));
135+
}
136+
return request;
137+
}
138+
}
139+
71140

72141
/**
73142
* Test {@code MockMvcConfigurer}.
@@ -80,8 +149,9 @@ public void afterConfigurerAdded(ConfigurableMockMvcBuilder<?> builder) {
80149
}
81150

82151
@Override
83-
public RequestPostProcessor beforeMockMvcCreated(ConfigurableMockMvcBuilder<?> builder,
84-
WebApplicationContext context) {
152+
public RequestPostProcessor beforeMockMvcCreated(
153+
ConfigurableMockMvcBuilder<?> builder, WebApplicationContext context) {
154+
85155
return request -> {
86156
request.setUserPrincipal(mock());
87157
return request;

spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/FrameworkExtensionTests.java

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import java.security.Principal;
2020

21-
import org.junit.jupiter.api.BeforeEach;
2221
import org.junit.jupiter.api.Test;
2322

2423
import org.springframework.http.HttpHeaders;
@@ -53,14 +52,9 @@
5352
*/
5453
public class FrameworkExtensionTests {
5554

56-
private MockMvc mockMvc;
55+
private final MockMvc mockMvc = standaloneSetup(new SampleController()).apply(defaultSetup()).build();
5756

5857

59-
@BeforeEach
60-
public void setup() {
61-
this.mockMvc = standaloneSetup(new SampleController()).apply(defaultSetup()).build();
62-
}
63-
6458
@Test
6559
public void fooHeader() throws Exception {
6660
this.mockMvc.perform(get("/").with(headers().foo("a=b"))).andExpect(content().string("Foo"));
@@ -81,7 +75,7 @@ private static TestRequestPostProcessor headers() {
8175

8276

8377
/**
84-
* Test {@code RequestPostProcessor}.
78+
* Test {@code RequestPostProcessor} for custom headers.
8579
*/
8680
private static class TestRequestPostProcessor implements RequestPostProcessor {
8781

@@ -119,8 +113,9 @@ public void afterConfigurerAdded(ConfigurableMockMvcBuilder<?> builder) {
119113
}
120114

121115
@Override
122-
public RequestPostProcessor beforeMockMvcCreated(ConfigurableMockMvcBuilder<?> builder,
123-
WebApplicationContext context) {
116+
public RequestPostProcessor beforeMockMvcCreated(
117+
ConfigurableMockMvcBuilder<?> builder, WebApplicationContext context) {
118+
124119
return request -> {
125120
request.setUserPrincipal(mock());
126121
return request;

0 commit comments

Comments
 (0)