Problem autowiring UserDetailsService while running tests

Viewed 107

I added spring security to my application and it's working great, but now existing tests are broken, when I run them I get:

***************************
APPLICATION FAILED TO START
***************************

Description:

Field userDetailsService in xxx.xxx.someapp.spring.security.WebSecurityConfig required a bean of type 'xxx.xxx.sardinatank.someapp.security.services.UserDetailsServiceImpl' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)

This is how I'm wiring the UserDetailsServiceImpl in my WebSecurityConfig

@Autowired
UserDetailsServiceImpl userDetailsService;

This is an example controller

@RestController
public class HelloWorldController {

  @GetMapping
  public ModelAndView helloWorld() {
    final ModelAndView bootstrapFront = new ModelAndView("index.html");
    return bootstrapFront;
  }
}

And this is a test that fails

@WebMvcTest(controllers = HelloWorldController.class)
@ContextConfiguration
@WebAppConfiguration
class HelloWorldControllerTest {

    @Autowired
    private WebApplicationContext webApplicationContext;

    private MockMvc mockMvc;

    @BeforeEach
    public void setup() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

    @Test
    public void getBootstrappedDoc() throws Exception {
        MvcResult mvcResult = mockMvc.perform(get("/"))
            .andExpect(status().isOk())
            .andReturn();
        assertEquals("index.html", mvcResult.getModelAndView().getViewName());
    }
}
1 Answers

I guess you might have declared it as a @Component or something that is not part of this list:

@Controller, @ControllerAdvice, @JsonComponent, Converter, Filter, WebMvcConfigurer

which means UserdetailServiceImpl will not be part of the @SpringWebMVC sliced test context, hence spring doesn't bootstrap it.

You have 2 options:

  • Either you decorate your UserServiceImpl with one of the aforementioned annotations: e.g
  @JsonComponent
  class UserDetailsServiceImpl implements userDetailsService { ... };
  • Or you inject a mock of UserServiceImpl in your test with @MockBean:
@WebMvcTest(controllers = HelloWorldController.class)
@ContextConfiguration
@WebAppConfiguration
class HelloWorldControllerTest {

  @Autowired
  private WebApplicationContext webApplicationContext;

  @MockBean
  UserDetailsServiceImpl userDetailsService;

  private MockMvc mockMvc;

  //...

}
Related