MockMvcHttpConnector supports RequestPostProcessor's
Closes gh-31298
This commit is contained in:
parent
0f6b018e97
commit
af7fe013b6
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2023 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -80,7 +80,7 @@ class DefaultWebTestClientBuilder implements WebTestClient.Builder {
|
||||||
private final WebHttpHandlerBuilder httpHandlerBuilder;
|
private final WebHttpHandlerBuilder httpHandlerBuilder;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private final ClientHttpConnector connector;
|
private ClientHttpConnector connector;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private String baseUrl;
|
private String baseUrl;
|
||||||
|
@ -277,6 +277,12 @@ class DefaultWebTestClientBuilder implements WebTestClient.Builder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WebTestClient.Builder clientConnector(ClientHttpConnector connector) {
|
||||||
|
this.connector = connector;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WebTestClient build() {
|
public WebTestClient build() {
|
||||||
ClientHttpConnector connectorToUse = this.connector;
|
ClientHttpConnector connectorToUse = this.connector;
|
||||||
|
|
|
@ -512,6 +512,18 @@ public interface WebTestClient {
|
||||||
*/
|
*/
|
||||||
Builder responseTimeout(Duration timeout);
|
Builder responseTimeout(Duration timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the {@link ClientHttpConnector} to use.
|
||||||
|
* <p>By default, this is initialized and set internally. However, the
|
||||||
|
* connector may also be prepared externally and passed via
|
||||||
|
* {@link WebTestClient#bindToServer(ClientHttpConnector)} such as for
|
||||||
|
* {@code MockMvcWebTestClient} tests, and in that case you can use this
|
||||||
|
* from {@link #mutateWith(WebTestClientConfigurer)} to replace it.
|
||||||
|
* @param connector the connector to use
|
||||||
|
* @since 6.1
|
||||||
|
*/
|
||||||
|
Builder clientConnector(ClientHttpConnector connector);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply the given configurer to this builder instance.
|
* Apply the given configurer to this builder instance.
|
||||||
* <p>This can be useful for applying pre-packaged customizations.
|
* <p>This can be useful for applying pre-packaged customizations.
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.springframework.test.web.servlet.client;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
@ -56,6 +57,7 @@ import org.springframework.test.web.servlet.RequestBuilder;
|
||||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||||
import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder;
|
import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder;
|
||||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||||
|
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
||||||
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
|
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
@ -82,9 +84,16 @@ public class MockMvcHttpConnector implements ClientHttpConnector {
|
||||||
|
|
||||||
private final MockMvc mockMvc;
|
private final MockMvc mockMvc;
|
||||||
|
|
||||||
|
private final List<RequestPostProcessor> requestPostProcessors;
|
||||||
|
|
||||||
|
|
||||||
public MockMvcHttpConnector(MockMvc mockMvc) {
|
public MockMvcHttpConnector(MockMvc mockMvc) {
|
||||||
|
this(mockMvc, Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private MockMvcHttpConnector(MockMvc mockMvc, List<RequestPostProcessor> requestPostProcessors) {
|
||||||
this.mockMvc = mockMvc;
|
this.mockMvc = mockMvc;
|
||||||
|
this.requestPostProcessors = new ArrayList<>(requestPostProcessors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -135,6 +144,8 @@ public class MockMvcHttpConnector implements ClientHttpConnector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.requestPostProcessors.forEach(requestBuilder::with);
|
||||||
|
|
||||||
return requestBuilder;
|
return requestBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,6 +218,15 @@ public class MockMvcHttpConnector implements ClientHttpConnector {
|
||||||
return clientResponse;
|
return clientResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance that applies the given {@link RequestPostProcessor}s
|
||||||
|
* to performed requests.
|
||||||
|
* @since 6.1
|
||||||
|
*/
|
||||||
|
public MockMvcHttpConnector with(List<RequestPostProcessor> postProcessors) {
|
||||||
|
return new MockMvcHttpConnector(this.mockMvc, postProcessors);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class MockMvcServerClientHttpResponse
|
private static class MockMvcServerClientHttpResponse
|
||||||
extends MockClientHttpResponse implements MockServerClientHttpResponse {
|
extends MockClientHttpResponse implements MockServerClientHttpResponse {
|
||||||
|
|
|
@ -17,11 +17,17 @@
|
||||||
package org.springframework.test.web.servlet.samples.client.standalone;
|
package org.springframework.test.web.servlet.samples.client.standalone;
|
||||||
|
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.client.reactive.ClientHttpConnector;
|
||||||
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
|
import org.springframework.test.web.reactive.server.WebTestClientConfigurer;
|
||||||
|
import org.springframework.test.web.servlet.client.MockMvcHttpConnector;
|
||||||
import org.springframework.test.web.servlet.client.MockMvcWebTestClient;
|
import org.springframework.test.web.servlet.client.MockMvcWebTestClient;
|
||||||
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
||||||
import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder;
|
import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder;
|
||||||
|
@ -30,6 +36,7 @@ import org.springframework.util.Assert;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
|
||||||
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
@ -50,16 +57,16 @@ public class FrameworkExtensionTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void fooHeader() {
|
public void fooHeader() {
|
||||||
this.client.get().uri("/")
|
this.client.mutateWith(headers().foo("a=b"))
|
||||||
.header("Foo", "a=b")
|
.get().uri("/")
|
||||||
.exchange()
|
.exchange()
|
||||||
.expectBody(String.class).isEqualTo("Foo");
|
.expectBody(String.class).isEqualTo("Foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void barHeader() {
|
public void barHeader() {
|
||||||
this.client.get().uri("/")
|
this.client.mutateWith(headers().bar("a=b"))
|
||||||
.header("Bar", "a=b")
|
.get().uri("/")
|
||||||
.exchange()
|
.exchange()
|
||||||
.expectBody(String.class).isEqualTo("Bar");
|
.expectBody(String.class).isEqualTo("Bar");
|
||||||
}
|
}
|
||||||
|
@ -68,6 +75,68 @@ public class FrameworkExtensionTests {
|
||||||
return new TestMockMvcConfigurer();
|
return new TestMockMvcConfigurer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static TestWebTestClientConfigurer headers() {
|
||||||
|
return new TestWebTestClientConfigurer();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test WebTestClientConfigurer that re-creates the MockMvcHttpConnector
|
||||||
|
* with a {@code TestRequestPostProcessor}.
|
||||||
|
*/
|
||||||
|
private static class TestWebTestClientConfigurer implements WebTestClientConfigurer {
|
||||||
|
|
||||||
|
private final TestRequestPostProcessor requestPostProcessor = new TestRequestPostProcessor();
|
||||||
|
|
||||||
|
public TestWebTestClientConfigurer foo(String value) {
|
||||||
|
this.requestPostProcessor.foo(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestWebTestClientConfigurer bar(String value) {
|
||||||
|
this.requestPostProcessor.bar(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterConfigurerAdded(
|
||||||
|
WebTestClient.Builder builder, WebHttpHandlerBuilder httpHandlerBuilder,
|
||||||
|
ClientHttpConnector connector) {
|
||||||
|
|
||||||
|
if (connector instanceof MockMvcHttpConnector mockMvcConnector) {
|
||||||
|
builder.clientConnector(mockMvcConnector.with(List.of(this.requestPostProcessor)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test {@code RequestPostProcessor} for custom headers.
|
||||||
|
*/
|
||||||
|
private static class TestRequestPostProcessor implements RequestPostProcessor {
|
||||||
|
|
||||||
|
private final HttpHeaders headers = new HttpHeaders();
|
||||||
|
|
||||||
|
|
||||||
|
public TestRequestPostProcessor foo(String value) {
|
||||||
|
this.headers.add("Foo", value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestRequestPostProcessor bar(String value) {
|
||||||
|
this.headers.add("Bar", value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
|
||||||
|
for (String headerName : this.headers.keySet()) {
|
||||||
|
request.addHeader(headerName, this.headers.get(headerName));
|
||||||
|
}
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test {@code MockMvcConfigurer}.
|
* Test {@code MockMvcConfigurer}.
|
||||||
|
@ -80,8 +149,9 @@ public class FrameworkExtensionTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RequestPostProcessor beforeMockMvcCreated(ConfigurableMockMvcBuilder<?> builder,
|
public RequestPostProcessor beforeMockMvcCreated(
|
||||||
WebApplicationContext context) {
|
ConfigurableMockMvcBuilder<?> builder, WebApplicationContext context) {
|
||||||
|
|
||||||
return request -> {
|
return request -> {
|
||||||
request.setUserPrincipal(mock());
|
request.setUserPrincipal(mock());
|
||||||
return request;
|
return request;
|
||||||
|
|
|
@ -18,7 +18,6 @@ package org.springframework.test.web.servlet.samples.standalone;
|
||||||
|
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
|
@ -53,14 +52,9 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standal
|
||||||
*/
|
*/
|
||||||
public class FrameworkExtensionTests {
|
public class FrameworkExtensionTests {
|
||||||
|
|
||||||
private MockMvc mockMvc;
|
private final MockMvc mockMvc = standaloneSetup(new SampleController()).apply(defaultSetup()).build();
|
||||||
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
public void setup() {
|
|
||||||
this.mockMvc = standaloneSetup(new SampleController()).apply(defaultSetup()).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void fooHeader() throws Exception {
|
public void fooHeader() throws Exception {
|
||||||
this.mockMvc.perform(get("/").with(headers().foo("a=b"))).andExpect(content().string("Foo"));
|
this.mockMvc.perform(get("/").with(headers().foo("a=b"))).andExpect(content().string("Foo"));
|
||||||
|
@ -81,7 +75,7 @@ public class FrameworkExtensionTests {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test {@code RequestPostProcessor}.
|
* Test {@code RequestPostProcessor} for custom headers.
|
||||||
*/
|
*/
|
||||||
private static class TestRequestPostProcessor implements RequestPostProcessor {
|
private static class TestRequestPostProcessor implements RequestPostProcessor {
|
||||||
|
|
||||||
|
@ -119,8 +113,9 @@ public class FrameworkExtensionTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RequestPostProcessor beforeMockMvcCreated(ConfigurableMockMvcBuilder<?> builder,
|
public RequestPostProcessor beforeMockMvcCreated(
|
||||||
WebApplicationContext context) {
|
ConfigurableMockMvcBuilder<?> builder, WebApplicationContext context) {
|
||||||
|
|
||||||
return request -> {
|
return request -> {
|
||||||
request.setUserPrincipal(mock());
|
request.setUserPrincipal(mock());
|
||||||
return request;
|
return request;
|
||||||
|
|
Loading…
Reference in New Issue