Support API versioning in MockMvc

See gh-34919
This commit is contained in:
rstoyanchev
2025-05-19 08:51:38 +01:00
parent a024e5985a
commit 3095219479
9 changed files with 254 additions and 15 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.http.HttpMethod;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockServletContext;
import org.springframework.web.client.ApiVersionInserter;
import static org.assertj.core.api.Assertions.assertThat;
@@ -96,6 +97,36 @@ class AbstractMockHttpServletRequestBuilderTests {
assertThat(request.getMethod()).isEqualTo(HttpMethod.POST.name());
}
@Test
void insertVersionInUrl() {
MockHttpServletRequest request = buildRequest(
new TestRequestBuilder(HttpMethod.GET).uri("/test")
.apiVersion(1.1)
.apiVersionInserter(ApiVersionInserter.usePathSegment(0)));
assertThat(request.getRequestURI()).isEqualTo("/1.1/test");
}
@Test
void insertVersionInHeader() {
MockHttpServletRequest request = buildRequest(
new TestRequestBuilder(HttpMethod.GET).uri("/test")
.apiVersion(1.1)
.apiVersionInserter(ApiVersionInserter.useHeader("API-Version")));
assertThat(request.getRequestURI()).isEqualTo("/test");
assertThat(request.getHeader("API-Version")).isEqualTo("1.1");
}
@Test
void mergeVersion() {
TestRequestBuilder builder = new TestRequestBuilder(HttpMethod.GET).uri("/b");
builder.merge(new TestRequestBuilder(HttpMethod.GET).uri("/a")
.apiVersion(1.1)
.apiVersionInserter(ApiVersionInserter.useHeader("API-Version")));
assertThat(buildRequest(builder).getHeader("API-Version")).isEqualTo("1.1");
}
private MockHttpServletRequest buildRequest(AbstractMockHttpServletRequestBuilder<?> builder) {
return builder.buildRequest(this.servletContext);

View File

@@ -0,0 +1,78 @@
/*
* Copyright 2002-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.test.web.servlet.samples.standalone;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.test.web.Person;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.accept.DefaultApiVersionStrategy;
import org.springframework.web.accept.SemanticApiVersionParser;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.ApiVersionInserter;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
/**
* Tests demonstrating the use of API version.
* @author Rossen Stoyanchev
*/
public class ApiVersionTests {
@Test
public void queryParameter() throws Exception {
String header = "API-Version";
DefaultApiVersionStrategy versionStrategy = new DefaultApiVersionStrategy(
List.of(request -> request.getHeader(header)),
new SemanticApiVersionParser(),
true, null);
MockMvc mockMvc = standaloneSetup(new PersonController())
.setApiVersionStrategy(versionStrategy)
.apiVersionInserter(ApiVersionInserter.useHeader(header))
.build();
mockMvc.perform(get("/search?name=George").accept(MediaType.APPLICATION_JSON).apiVersion(1.1))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json"))
.andExpect(jsonPath("$.name").value("George"));
}
@Controller
private static class PersonController {
@RequestMapping(path="/search", version = "1.1")
@ResponseBody
public Person get(@RequestParam String name) {
return new Person(name);
}
}
}

View File

@@ -36,6 +36,7 @@ import org.springframework.http.support.JacksonHandlerInstantiator;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.accept.ApiVersionStrategy;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
@@ -74,6 +75,18 @@ class StandaloneMockMvcBuilderTests {
assertThat(((HandlerMethod) chain.getHandler()).getMethod().getName()).isEqualTo("handleWithPlaceholders");
}
@Test
void apiVersionStrategySet() {
ApiVersionStrategy versionStrategy = mock(ApiVersionStrategy.class);
TestStandaloneMockMvcBuilder builder = new TestStandaloneMockMvcBuilder();
builder.setApiVersionStrategy(versionStrategy);
builder.build();
assertThat(builder.wac.getBean(RequestMappingHandlerMapping.class).getApiVersionStrategy())
.isSameAs(versionStrategy);
}
@Test // SPR-12553
void applicationContextAttribute() {
TestStandaloneMockMvcBuilder builder = new TestStandaloneMockMvcBuilder(new PlaceholderController());