Kars
Kars

Reputation: 917

Spring security test with userDetailsService gives illegalStateException in test case

I have some spring controller tests that worked fine before. I recently added authentication using a userDetailsService, and now when i run controller tests it says this:

java.lang.IllegalStateException: Failed to load ApplicationContext
...
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'nl.kars.lms.service.MyUserDetailsService' available: 
expected at least 1 bean which qualifies as autowire candidate.

I don't understand why, because everything should be configured correctly. It only happens when running the controller tests, running the app works perfectly fine. Here are my classes.

Test case

@RunWith(SpringRunner.class)
@WebMvcTest(ActionController.class)
public class ActionControllerTests {

    @Autowired
    private MockMvc mvc;

    @MockBean
    private ActionService service;

    @Test
    public void testGetActions_returns_result_from_service() throws Exception {
        int actionId = 1;
        Action action = new Action();
        action.setId(actionId);
        List<Action> actionsList = Arrays.asList(action);

        given(service.getActions()).willReturn(actionsList);

        mvc.perform(get("/actions")
                .contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$", hasSize(1)))
                .andExpect(jsonPath("$[0].id", Matchers.is(actionId)));
    }
}

Configuration

@EnableWebSecurity
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    MyUserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors();
        http.csrf().disable()
                .authorizeRequests()
                .antMatchers("/**")
                .fullyAuthenticated()
                .and().httpBasic();
    }

    @Bean
    public PasswordEncoder getPasswordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
}

UserDetailsService

@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private EmployeeService employeeService;

    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        return new EmployeeDetails(employeeService.getEmployeeByEmail(email));
    }
}

My question is, how do i stop the error from occuring? What am i doing wrong? I am lost at this point. Thanks

Upvotes: 0

Views: 350

Answers (1)

Shreyas B
Shreyas B

Reputation: 505

Since you have named Your MyUserDetailsService as userDetailsService in @Service("userDetailsService") you have two options

First One :
Use @Qualifier("userDetailsService") in SecurityConfiguration.

Second Option:
Autowire UserDetailsService instead of MyUserDetailsService in SecurityConfiguration.

I suggest you try the first option

@Autowired
@Qualifier("userDetailsService")
MyUserDetailsService userDetailsService;

Upvotes: 1

Related Questions