Skip to content

Commit d2225c2

Browse files
committed
MockMvc supports FilterRegistration filter init
Closes gh-33252
1 parent 3845391 commit d2225c2

File tree

4 files changed

+176
-27
lines changed

4 files changed

+176
-27
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Copyright 2002-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.mock.web;
18+
19+
import java.util.ArrayList;
20+
import java.util.Arrays;
21+
import java.util.Collection;
22+
import java.util.Collections;
23+
import java.util.EnumSet;
24+
import java.util.LinkedHashMap;
25+
import java.util.LinkedHashSet;
26+
import java.util.List;
27+
import java.util.Map;
28+
import java.util.Set;
29+
30+
import jakarta.servlet.DispatcherType;
31+
import jakarta.servlet.FilterRegistration;
32+
33+
import org.springframework.lang.Nullable;
34+
35+
/**
36+
* Mock implementation of {@link FilterRegistration}.
37+
*
38+
* @author Rossen Stoyanchev
39+
* @since 6.2
40+
*/
41+
public class MockFilterRegistration implements FilterRegistration {
42+
43+
private final String name;
44+
45+
private final String className;
46+
47+
private final Map<String, String> initParameters = new LinkedHashMap<>();
48+
49+
private final List<String> servletNames = new ArrayList<>();
50+
51+
private final List<String> urlPatterns = new ArrayList<>();
52+
53+
54+
public MockFilterRegistration(String className) {
55+
this(className, "");
56+
}
57+
58+
public MockFilterRegistration(String className, String name) {
59+
this.name = name;
60+
this.className = className;
61+
}
62+
63+
64+
@Override
65+
public String getName() {
66+
return this.name;
67+
}
68+
69+
@Nullable
70+
@Override
71+
public String getClassName() {
72+
return this.className;
73+
}
74+
75+
@Override
76+
public boolean setInitParameter(String name, String value) {
77+
return (this.initParameters.putIfAbsent(name, value) != null);
78+
}
79+
80+
@Nullable
81+
@Override
82+
public String getInitParameter(String name) {
83+
return this.initParameters.get(name);
84+
}
85+
86+
@Override
87+
public Set<String> setInitParameters(Map<String, String> initParameters) {
88+
Set<String> existingParameterNames = new LinkedHashSet<>();
89+
for (Map.Entry<String, String> entry : initParameters.entrySet()) {
90+
if (this.initParameters.get(entry.getKey()) != null) {
91+
existingParameterNames.add(entry.getKey());
92+
}
93+
}
94+
if (existingParameterNames.isEmpty()) {
95+
this.initParameters.putAll(initParameters);
96+
}
97+
return existingParameterNames;
98+
}
99+
100+
@Override
101+
public Map<String, String> getInitParameters() {
102+
return Collections.unmodifiableMap(this.initParameters);
103+
}
104+
105+
@Override
106+
public void addMappingForServletNames(
107+
EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... servletNames) {
108+
109+
this.servletNames.addAll(Arrays.asList(servletNames));
110+
}
111+
112+
@Override
113+
public Collection<String> getServletNameMappings() {
114+
return Collections.unmodifiableCollection(this.servletNames);
115+
}
116+
117+
@Override
118+
public void addMappingForUrlPatterns(
119+
EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... urlPatterns) {
120+
121+
this.urlPatterns.addAll(Arrays.asList(urlPatterns));
122+
}
123+
124+
@Override
125+
public Collection<String> getUrlPatternMappings() {
126+
return Collections.unmodifiableCollection(this.urlPatterns);
127+
}
128+
129+
}

spring-test/src/main/java/org/springframework/mock/web/MockServletContext.java

+21-19
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ public class MockServletContext implements ServletContext {
145145
@Nullable
146146
private String responseCharacterEncoding;
147147

148+
private final Map<String, FilterRegistration> filterRegistrations = new LinkedHashMap<>();
149+
148150
private final Map<String, MediaType> mimeTypes = new LinkedHashMap<>();
149151

150152

@@ -604,6 +606,25 @@ public String getResponseCharacterEncoding() {
604606
return this.responseCharacterEncoding;
605607
}
606608

609+
/**
610+
* Add a {@link FilterRegistration}.
611+
* @since 6.2
612+
*/
613+
public void addFilterRegistration(FilterRegistration registration) {
614+
this.filterRegistrations.put(registration.getName(), registration);
615+
}
616+
617+
@Override
618+
@Nullable
619+
public FilterRegistration getFilterRegistration(String filterName) {
620+
return this.filterRegistrations.get(filterName);
621+
}
622+
623+
@Override
624+
public Map<String, ? extends FilterRegistration> getFilterRegistrations() {
625+
return Collections.unmodifiableMap(this.filterRegistrations);
626+
}
627+
607628

608629
//---------------------------------------------------------------------
609630
// Unsupported Servlet 3.0 registration methods
@@ -678,25 +699,6 @@ public <T extends Filter> T createFilter(Class<T> c) throws ServletException {
678699
throw new UnsupportedOperationException();
679700
}
680701

681-
/**
682-
* This method always returns {@code null}.
683-
* @see jakarta.servlet.ServletContext#getFilterRegistration(java.lang.String)
684-
*/
685-
@Override
686-
@Nullable
687-
public FilterRegistration getFilterRegistration(String filterName) {
688-
return null;
689-
}
690-
691-
/**
692-
* This method always returns an {@linkplain Collections#emptyMap empty map}.
693-
* @see jakarta.servlet.ServletContext#getFilterRegistrations()
694-
*/
695-
@Override
696-
public Map<String, ? extends FilterRegistration> getFilterRegistrations() {
697-
return Collections.emptyMap();
698-
}
699-
700702
@Override
701703
public void addListener(Class<? extends EventListener> listenerClass) {
702704
throw new UnsupportedOperationException();

spring-test/src/main/java/org/springframework/test/web/servlet/setup/MockMvcFilterDecorator.java

+17-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 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.
@@ -35,6 +35,8 @@
3535

3636
import org.springframework.lang.Nullable;
3737
import org.springframework.mock.web.MockFilterConfig;
38+
import org.springframework.mock.web.MockFilterRegistration;
39+
import org.springframework.mock.web.MockServletContext;
3840
import org.springframework.util.Assert;
3941
import org.springframework.web.util.UrlPathHelper;
4042

@@ -98,17 +100,27 @@ public MockMvcFilterDecorator(
98100
Assert.notNull(delegate, "filter cannot be null");
99101
Assert.notNull(urlPatterns, "urlPatterns cannot be null");
100102
this.delegate = delegate;
101-
this.filterConfigInitializer = getFilterConfigInitializer(filterName, initParams);
103+
this.filterConfigInitializer = getFilterConfigInitializer(delegate, filterName, initParams);
102104
this.dispatcherTypes = dispatcherTypes;
103105
this.hasPatterns = initPatterns(urlPatterns);
104106
}
105107

106108
private static Function<ServletContext, FilterConfig> getFilterConfigInitializer(
107-
@Nullable String filterName, @Nullable Map<String, String> initParams) {
109+
Filter delegate, @Nullable String filterName, @Nullable Map<String, String> initParams) {
110+
111+
String className = delegate.getClass().getName();
108112

109113
return servletContext -> {
110-
MockFilterConfig filterConfig = (filterName != null ?
111-
new MockFilterConfig(servletContext, filterName) : new MockFilterConfig(servletContext));
114+
MockServletContext mockServletContext = (MockServletContext) servletContext;
115+
MockFilterConfig filterConfig;
116+
if (filterName != null) {
117+
filterConfig = new MockFilterConfig(servletContext, filterName);
118+
mockServletContext.addFilterRegistration(new MockFilterRegistration(className, filterName));
119+
}
120+
else {
121+
filterConfig = new MockFilterConfig(servletContext);
122+
mockServletContext.addFilterRegistration(new MockFilterRegistration(className));
123+
}
112124
if (initParams != null) {
113125
initParams.forEach(filterConfig::addInitParameter);
114126
}

spring-test/src/test/java/org/springframework/test/web/servlet/setup/StandaloneMockMvcBuilderTests.java

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 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.
@@ -35,6 +35,7 @@
3535
import org.springframework.http.converter.json.SpringHandlerInstantiator;
3636
import org.springframework.mock.web.MockHttpServletRequest;
3737
import org.springframework.stereotype.Controller;
38+
import org.springframework.test.web.servlet.MockMvc;
3839
import org.springframework.web.bind.annotation.RequestMapping;
3940
import org.springframework.web.context.WebApplicationContext;
4041
import org.springframework.web.context.support.WebApplicationContextUtils;
@@ -133,12 +134,17 @@ void addFilterWithInitParams() throws ServletException {
133134
Filter filter = mock(Filter.class);
134135
ArgumentCaptor<FilterConfig> captor = ArgumentCaptor.forClass(FilterConfig.class);
135136

136-
MockMvcBuilders.standaloneSetup(new PersonController())
137-
.addFilter(filter, null, Map.of("p", "v"), EnumSet.of(DispatcherType.REQUEST), "/")
137+
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new PersonController())
138+
.addFilter(filter, "testFilter", Map.of("p", "v"), EnumSet.of(DispatcherType.REQUEST), "/")
138139
.build();
139140

140141
verify(filter, times(1)).init(captor.capture());
141142
assertThat(captor.getValue().getInitParameter("p")).isEqualTo("v");
143+
144+
// gh-33252
145+
146+
assertThat(mockMvc.getDispatcherServlet().getServletContext().getFilterRegistrations())
147+
.hasSize(1).containsKey("testFilter");
142148
}
143149

144150
@Test // SPR-13375

0 commit comments

Comments
 (0)