2727import org .springframework .boot .context .properties .EnableConfigurationProperties ;
2828import org .springframework .boot .test .context .FilteredClassLoader ;
2929import org .springframework .boot .test .context .runner .ApplicationContextRunner ;
30+ import org .springframework .boot .test .context .runner .ReactiveWebApplicationContextRunner ;
31+ import org .springframework .boot .test .context .runner .WebApplicationContextRunner ;
3032import org .springframework .boot .test .system .CapturedOutput ;
3133import org .springframework .boot .test .system .OutputCaptureExtension ;
3234import org .springframework .context .annotation .Bean ;
5658 *
5759 * @author Madhura Bhave
5860 * @author HaiTao Zhang
61+ * @author Lasse Wulff
62+ * @author Moritz Halbritter
5963 */
6064@ ExtendWith (OutputCaptureExtension .class )
6165class UserDetailsServiceAutoConfigurationTests {
6266
63- private final ApplicationContextRunner contextRunner = new ApplicationContextRunner ()
67+ private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner ()
6468 .withUserConfiguration (TestSecurityConfiguration .class )
6569 .withConfiguration (AutoConfigurations .of (UserDetailsServiceAutoConfiguration .class ));
6670
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+
6793 @ Test
6894 void testDefaultUsernamePassword (CapturedOutput output ) {
69- this .contextRunner .with (noOtherFormsOfAuthenticationOnTheClasspath ()).run ((context ) -> {
95+ this .contextRunner .with (AuthenticationExclude . servletApp ()).run ((context ) -> {
7096 UserDetailsService manager = context .getBean (UserDetailsService .class );
7197 assertThat (output ).contains ("Using generated security password:" );
7298 assertThat (manager .loadUserByUsername ("user" )).isNotNull ();
@@ -128,7 +154,7 @@ void defaultUserNotCreatedIfResourceServerWithJWTIsUsed() {
128154
129155 @ Test
130156 void userDetailsServiceWhenPasswordEncoderAbsentAndDefaultPassword () {
131- this .contextRunner .with (noOtherFormsOfAuthenticationOnTheClasspath ())
157+ this .contextRunner .with (AuthenticationExclude . servletApp ())
132158 .withUserConfiguration (TestSecurityConfiguration .class )
133159 .run (((context ) -> {
134160 InMemoryUserDetailsManager userDetailsService = context .getBean (InMemoryUserDetailsManager .class );
@@ -192,14 +218,8 @@ void userDetailsServiceWhenRelyingPartyRegistrationRepositoryPresentAndPasswordC
192218 .run (((context ) -> assertThat (context ).hasSingleBean (InMemoryUserDetailsManager .class )));
193219 }
194220
195- private Function <ApplicationContextRunner , ApplicationContextRunner > noOtherFormsOfAuthenticationOnTheClasspath () {
196- return (contextRunner ) -> contextRunner
197- .withClassLoader (new FilteredClassLoader (ClientRegistrationRepository .class , OpaqueTokenIntrospector .class ,
198- RelyingPartyRegistrationRepository .class ));
199- }
200-
201221 private void testPasswordEncoding (Class <?> configClass , String providedPassword , String expectedPassword ) {
202- this .contextRunner .with (noOtherFormsOfAuthenticationOnTheClasspath ())
222+ this .contextRunner .with (AuthenticationExclude . servletApp ())
203223 .withClassLoader (new FilteredClassLoader (ClientRegistrationRepository .class , OpaqueTokenIntrospector .class ,
204224 RelyingPartyRegistrationRepository .class ))
205225 .withUserConfiguration (configClass )
@@ -211,6 +231,26 @@ private void testPasswordEncoding(Class<?> configClass, String providedPassword,
211231 }));
212232 }
213233
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+
214254 @ Configuration (proxyBeanMethods = false )
215255 static class TestAuthenticationManagerConfiguration {
216256
0 commit comments