2626import org .springframework .boot .autoconfigure .security .SecurityProperties ;
2727import org .springframework .boot .context .properties .EnableConfigurationProperties ;
2828import org .springframework .boot .test .context .FilteredClassLoader ;
29+ import org .springframework .boot .test .context .runner .ApplicationContextRunner ;
30+ import org .springframework .boot .test .context .runner .ReactiveWebApplicationContextRunner ;
2931import org .springframework .boot .test .context .runner .WebApplicationContextRunner ;
3032import org .springframework .boot .test .system .CapturedOutput ;
3133import org .springframework .boot .test .system .OutputCaptureExtension ;
5759 * @author Madhura Bhave
5860 * @author HaiTao Zhang
5961 * @author Lasse Wulff
62+ * @author Moritz Halbritter
6063 */
6164@ ExtendWith (OutputCaptureExtension .class )
6265class UserDetailsServiceAutoConfigurationTests {
@@ -65,9 +68,31 @@ class UserDetailsServiceAutoConfigurationTests {
6568 .withUserConfiguration (TestSecurityConfiguration .class )
6669 .withConfiguration (AutoConfigurations .of (UserDetailsServiceAutoConfiguration .class ));
6770
71+ @ Test
72+ void shouldSupplyUserDetailsServiceInServletApp () {
73+ this .contextRunner .with (AuthenticationExclude .servletApp ())
74+ .run ((context ) -> assertThat (context ).hasSingleBean (UserDetailsService .class ));
75+ }
76+
77+ @ Test
78+ void shouldNotSupplyUserDetailsServiceInReactiveApp () {
79+ new ReactiveWebApplicationContextRunner ().withUserConfiguration (TestSecurityConfiguration .class )
80+ .withConfiguration (AutoConfigurations .of (UserDetailsServiceAutoConfiguration .class ))
81+ .with (AuthenticationExclude .reactiveApp ())
82+ .run ((context ) -> assertThat (context ).doesNotHaveBean (UserDetailsService .class ));
83+ }
84+
85+ @ Test
86+ void shouldNotSupplyUserDetailsServiceInNonWebApp () {
87+ new ApplicationContextRunner ().withUserConfiguration (TestSecurityConfiguration .class )
88+ .withConfiguration (AutoConfigurations .of (UserDetailsServiceAutoConfiguration .class ))
89+ .with (AuthenticationExclude .noWebApp ())
90+ .run ((context ) -> assertThat (context ).doesNotHaveBean (UserDetailsService .class ));
91+ }
92+
6893 @ Test
6994 void testDefaultUsernamePassword (CapturedOutput output ) {
70- this .contextRunner .with (noOtherFormsOfAuthenticationOnTheClasspath ()).run ((context ) -> {
95+ this .contextRunner .with (AuthenticationExclude . servletApp ()).run ((context ) -> {
7196 UserDetailsService manager = context .getBean (UserDetailsService .class );
7297 assertThat (output ).contains ("Using generated security password:" );
7398 assertThat (manager .loadUserByUsername ("user" )).isNotNull ();
@@ -129,7 +154,7 @@ void defaultUserNotCreatedIfResourceServerWithJWTIsUsed() {
129154
130155 @ Test
131156 void userDetailsServiceWhenPasswordEncoderAbsentAndDefaultPassword () {
132- this .contextRunner .with (noOtherFormsOfAuthenticationOnTheClasspath ())
157+ this .contextRunner .with (AuthenticationExclude . servletApp ())
133158 .withUserConfiguration (TestSecurityConfiguration .class )
134159 .run (((context ) -> {
135160 InMemoryUserDetailsManager userDetailsService = context .getBean (InMemoryUserDetailsManager .class );
@@ -193,14 +218,8 @@ void userDetailsServiceWhenRelyingPartyRegistrationRepositoryPresentAndPasswordC
193218 .run (((context ) -> assertThat (context ).hasSingleBean (InMemoryUserDetailsManager .class )));
194219 }
195220
196- private Function <WebApplicationContextRunner , WebApplicationContextRunner > noOtherFormsOfAuthenticationOnTheClasspath () {
197- return (contextRunner ) -> contextRunner
198- .withClassLoader (new FilteredClassLoader (ClientRegistrationRepository .class , OpaqueTokenIntrospector .class ,
199- RelyingPartyRegistrationRepository .class ));
200- }
201-
202221 private void testPasswordEncoding (Class <?> configClass , String providedPassword , String expectedPassword ) {
203- this .contextRunner .with (noOtherFormsOfAuthenticationOnTheClasspath ())
222+ this .contextRunner .with (AuthenticationExclude . servletApp ())
204223 .withClassLoader (new FilteredClassLoader (ClientRegistrationRepository .class , OpaqueTokenIntrospector .class ,
205224 RelyingPartyRegistrationRepository .class ))
206225 .withUserConfiguration (configClass )
@@ -212,6 +231,26 @@ private void testPasswordEncoding(Class<?> configClass, String providedPassword,
212231 }));
213232 }
214233
234+ private static final class AuthenticationExclude {
235+
236+ private static final FilteredClassLoader filteredClassLoader = new FilteredClassLoader (
237+ ClientRegistrationRepository .class , OpaqueTokenIntrospector .class ,
238+ RelyingPartyRegistrationRepository .class );
239+
240+ static Function <WebApplicationContextRunner , WebApplicationContextRunner > servletApp () {
241+ return (contextRunner ) -> contextRunner .withClassLoader (filteredClassLoader );
242+ }
243+
244+ static Function <ReactiveWebApplicationContextRunner , ReactiveWebApplicationContextRunner > reactiveApp () {
245+ return (contextRunner ) -> contextRunner .withClassLoader (filteredClassLoader );
246+ }
247+
248+ static Function <ApplicationContextRunner , ApplicationContextRunner > noWebApp () {
249+ return (contextRunner ) -> contextRunner .withClassLoader (filteredClassLoader );
250+ }
251+
252+ }
253+
215254 @ Configuration (proxyBeanMethods = false )
216255 static class TestAuthenticationManagerConfiguration {
217256
0 commit comments