I'm writing an end-to-end test for the following class in my Spring boot project, but I receive org.springframework.beans.factory.NoSuchBeanDefinitionException error because No qualifying bean of type 'com.boot.cut_costs.service.CustomUserDetailsService' available.
@RestController
public class AuthenticationController {
@Autowired
protected AuthenticationManager authenticationManager;
@Autowired
private CustomUserDetailsService userDetailsServices;
@Autowired
private UserDetailsDtoValidator createUserDetailsDtoValidator;
@RequestMapping(value = "/signup", method = RequestMethod.POST)
public void create(@RequestBody UserDetailsDto userDetailsDTO, HttpServletResponse response, BindingResult result) {
// ...
userDetailsServices.saveIfNotExists(username, password, name);
// ...
if (authenticatedUser != null) {
AuthenticationService.addAuthentication(response, authenticatedUser.getName());
SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
} else {
throw new BadCredentialsException("Bad credentials provided");
}
}
}
Test class:
@RunWith(SpringRunner.class)
@WebMvcTest(AuthenticationController.class)
public class AuthenticationControllerFTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private AuthenticationManager authenticationManager;
@Test
public void testCreate() throws Exception {
Authentication authentication = Mockito.mock(Authentication.class);
Mockito.when(authentication.getName()).thenReturn("DUMMY_USERNAME");
Mockito.when(
authenticationManager.authenticate(Mockito
.any(UsernamePasswordAuthenticationToken.class)))
.thenReturn(authentication);
//....
RequestBuilder requestBuilder = MockMvcRequestBuilders
.post("/signup")
.accept(MediaType.APPLICATION_JSON).content(exampleUserInfo)
.contentType(MediaType.APPLICATION_JSON);
MvcResult result = mockMvc.perform(requestBuilder).andReturn();
MockHttpServletResponse response = result.getResponse();
}
}
I think this error happens because it in the test environment the spring context isn't loaded the same way as in dev/production environment. How should I fix this issue ?
Edit 1
My Spring boot application entry point is App.java:
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
@WebMvcTest only loads the controller configuration. That's why you had this DI error (with it, you have to provide mocks for your services). So, if you need to inject your services, you can use @SpringBootTest.
If you use @SpringBootTest, you also have to use @AutoConfigureMockMvcto configure MockMvc.
You need to pull in the configuration which does the component scanning for your beans using @ContextConfiguration annotation on your test class.
This could potentially load configuration that is not needed or may even cause the tests to fail so a safer way to do it would be to write a configuration class yourself with only what you need to get the test to run (potentially just the relevant component scan for your beans). If you write this config class as a static inner class of your test class then you can pull this config in by just using the @ContextConfiguration annotation with no parameters.
@ContextConfiguration
public class MyTestClass {
@Test
public void myTest() {
...
}
@Configuration
@ComponentScan("my.package")
public static class MyTestConfig {
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With