1818
1919import java .lang .reflect .Field ;
2020import java .lang .reflect .Modifier ;
21+ import java .util .LinkedHashMap ;
2122import java .util .List ;
23+ import java .util .Map ;
2224
2325import javax .servlet .DispatcherType ;
26+ import javax .servlet .Servlet ;
27+ import javax .servlet .ServletContext ;
28+ import javax .servlet .ServletRegistration ;
2429
30+ import org .jetbrains .annotations .NotNull ;
2531import org .junit .jupiter .api .BeforeEach ;
2632import org .junit .jupiter .api .Test ;
2733
3440import org .springframework .security .web .util .matcher .DispatcherTypeRequestMatcher ;
3541import org .springframework .security .web .util .matcher .RegexRequestMatcher ;
3642import org .springframework .security .web .util .matcher .RequestMatcher ;
43+ import org .springframework .web .context .WebApplicationContext ;
44+ import org .springframework .web .servlet .DispatcherServlet ;
3745
3846import static org .assertj .core .api .Assertions .assertThat ;
3947import static org .assertj .core .api .Assertions .assertThatExceptionOfType ;
@@ -56,12 +64,17 @@ public <O> O postProcess(O object) {
5664
5765 private TestRequestMatcherRegistry matcherRegistry ;
5866
67+ private WebApplicationContext context ;
68+
5969 @ BeforeEach
6070 public void setUp () {
6171 this .matcherRegistry = new TestRequestMatcherRegistry ();
62- ApplicationContext context = mock (ApplicationContext .class );
63- given (context .getBean (ObjectPostProcessor .class )).willReturn (NO_OP_OBJECT_POST_PROCESSOR );
64- this .matcherRegistry .setApplicationContext (context );
72+ this .context = mock (WebApplicationContext .class );
73+ ServletContext servletContext = new MockServletContext ();
74+ servletContext .addServlet ("dispatcherServlet" , DispatcherServlet .class );
75+ given (this .context .getBean (ObjectPostProcessor .class )).willReturn (NO_OP_OBJECT_POST_PROCESSOR );
76+ given (this .context .getServletContext ()).willReturn (servletContext );
77+ this .matcherRegistry .setApplicationContext (this .context );
6578 }
6679
6780 @ Test
@@ -184,6 +197,32 @@ public void requestMatchersWhenMvcPresentInClassPathAndMvcIntrospectorBeanNotAva
184197 "Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext" );
185198 }
186199
200+ @ Test
201+ public void requestMatchersWhenNoDispatcherServletThenAntPathRequestMatcherType () {
202+ MockServletContext servletContext = new MockServletContext ();
203+ given (this .context .getServletContext ()).willReturn (servletContext );
204+ List <RequestMatcher > requestMatchers = this .matcherRegistry .requestMatchers ("/**" );
205+ assertThat (requestMatchers ).isNotEmpty ();
206+ assertThat (requestMatchers ).hasSize (1 );
207+ assertThat (requestMatchers .get (0 )).isExactlyInstanceOf (AntPathRequestMatcher .class );
208+ servletContext .addServlet ("servletOne" , Servlet .class );
209+ servletContext .addServlet ("servletTwo" , Servlet .class );
210+ requestMatchers = this .matcherRegistry .requestMatchers ("/**" );
211+ assertThat (requestMatchers ).isNotEmpty ();
212+ assertThat (requestMatchers ).hasSize (1 );
213+ assertThat (requestMatchers .get (0 )).isExactlyInstanceOf (AntPathRequestMatcher .class );
214+ }
215+
216+ @ Test
217+ public void requestMatchersWhenAmbiguousServletsThenException () {
218+ MockServletContext servletContext = new MockServletContext ();
219+ given (this .context .getServletContext ()).willReturn (servletContext );
220+ servletContext .addServlet ("dispatcherServlet" , DispatcherServlet .class );
221+ servletContext .addServlet ("servletTwo" , Servlet .class );
222+ assertThatExceptionOfType (IllegalArgumentException .class )
223+ .isThrownBy (() -> this .matcherRegistry .requestMatchers ("/**" ));
224+ }
225+
187226 private void mockMvcIntrospector (boolean isPresent ) {
188227 ApplicationContext context = this .matcherRegistry .getApplicationContext ();
189228 given (context .containsBean ("mvcHandlerMappingIntrospector" )).willReturn (isPresent );
@@ -217,4 +256,25 @@ protected List<RequestMatcher> chainRequestMatchers(List<RequestMatcher> request
217256
218257 }
219258
259+ private static class MockServletContext extends org .springframework .mock .web .MockServletContext {
260+
261+ private final Map <String , ServletRegistration > registrations = new LinkedHashMap <>();
262+
263+ @ NotNull
264+ @ Override
265+ public ServletRegistration .Dynamic addServlet (@ NotNull String servletName , Class <? extends Servlet > clazz ) {
266+ ServletRegistration .Dynamic dynamic = mock (ServletRegistration .Dynamic .class );
267+ given (dynamic .getClassName ()).willReturn (clazz .getName ());
268+ this .registrations .put (servletName , dynamic );
269+ return dynamic ;
270+ }
271+
272+ @ NotNull
273+ @ Override
274+ public Map <String , ? extends ServletRegistration > getServletRegistrations () {
275+ return this .registrations ;
276+ }
277+
278+ }
279+
220280}
0 commit comments