Spring Boot: How to test controller and services with custom autowired components in configuration

Viewed 125

I am trying to learn more about testing in a spring boot project.
The following example shows a very simple test that checks the response of a service or endpoint.

@WebMvcTest(MyController.class)
public class MyControllerTests {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private MyService service;

    @Test
    public void getPing() throws Exception {
        when(service.ping()).thenReturn("pong");
        this.mockMvc.perform(get("/ping")).andDo(print()).andExpect(status().isOk())
            .andExpect(content().string(containsString("pong")));
    }
}

As soon as an individualized security config with custom components is used the test fails with NoSuchBeanDefinitionException.
For example: Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'my.project.component.MyLogoutSuccessHandler' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

The security configuration looks like this:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Configuration
    @Order(1)
    public static class FooConfigurationAdapter extends WebSecurityConfigurerAdapter {

        private final MyLogoutSuccessHandler myLogoutSuccessHandler;
        private final MyAuthenticationEntryPoint myAuthenticationEntryPoint;

        @Autowired
        FooConfigurationAdapter(MyLogoutSuccessHandler myLogoutSuccessHandler,
                                MyAuthenticationEntryPoint myAuthenticationEntryPoint) {
            this.myLogoutSuccessHandler = myLogoutSuccessHandler;
            this.myAuthenticationEntryPoint = myAuthenticationEntryPoint;
        }

        protected void configure(HttpSecurity http) throws Exception {
            // ...
        }
    }

    @Configuration
    @Order(2)
    public static class BarConfigurationAdapter extends WebSecurityConfigurerAdapter {

        private final MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
        private final UserDetailsService userDetailsService;

        @Autowired
        BarConfigurationAdapter(MyAuthenticationSuccessHandler myAuthenticationSuccessHandler,
                                 UserDetailsService userDetailsService) {
            this.myAuthenticationSuccessHandler = myAuthenticationSuccessHandler;
            this.userDetailsService = userDetailsService;
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            // ...
        }
    }
}

MyLogoutSuccessHandler looks like the following in this example:

@Component
public class MyLogoutSuccessHandler implements LogoutSuccessHandler {
    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,                                Authentication authentication) {
        // ...
    }
}

Can someone please explain to me how the test must look like to work with the autowired components?

0 Answers
Related