Spring引导jUnit测试失败的原因是" org.springframework.beans.factory.NoSuchBeanDefinitionException"

时间:2017-07-19 08:22:42

标签: java spring

我在Spring启动项目中为以下类编写了端到端测试,但由于org.springframework.beans.factory.NoSuchBeanDefinitionException我收到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");
        }
    }
}

测试类:

@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();
    }
}

我认为发生此错误是因为它在测试环境中弹出上下文的加载方式与开发/生产环境相同。我该如何解决这个问题?

修改1

我的Spring启动应用程序入口点为App.java

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

2 个答案:

答案 0 :(得分:2)

@WebMvcTest仅加载控制器配置。这就是为什么你有这个DI错误(有了它,你必须为你的服务提供模拟)。因此,如果您需要注入服务,可以使用@SpringBootTest

如果您使用@SpringBootTest,则还必须使用@AutoConfigureMockMvc配置MockMvc

答案 1 :(得分:0)

您需要使用测试类上的@ContextConfiguration批注拉入为bean扫描组件的配置。

这可能会加载不需要的配置,甚至可能导致测试失败,因此更安全的方法是自己编写配置类,只需要运行测试所需的内容(可能只是您的bean的相关组件扫描)。如果将此配置类编写为测试类的静态内部类,则可以通过仅使用不带参数的@ContextConfiguration注释来提取此配置。

@ContextConfiguration
public class MyTestClass {

   @Test
   public void myTest() {
     ...
   }

   @Configuration
   @ComponentScan("my.package")
   public static class MyTestConfig {
   }