@WebMvcTest 测试类中的 UnsatisfiedDependencyException

Posted

技术标签:

【中文标题】@WebMvcTest 测试类中的 UnsatisfiedDependencyException【英文标题】:UnsatisfiedDependencyException in a @WebMvcTest test class 【发布时间】:2018-10-04 16:47:50 【问题描述】:

将@Service 添加到控制器后,我的单元测试失败。 该项目是 Spring-boot v 2.0.1.RELEASE。我花了很多时间试图找到答案,但没有运气。在我添加 @Service 注释并且我的服务类中有一个存储库之前,该测试有效。

堆栈跟踪:

2018-04-24 12:57:12.487 警告 940 --- [主要] o.s.w.c.s.GenericWebApplicationContext:遇到异常 在上下文初始化期间 - 取消刷新尝试: org.springframework.beans.factory.UnsatisfiedDependencyException: 创建名为“fleetController”的 bean 时出错:不满意 通过字段“服务”表达的依赖关系;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException: 否 'uk.co.vw.lead.service.ContactUsService' 类型的合格 bean 可用:预计至少有 1 个符合 autowire 条件的 bean 候选人。依赖注解: @org.springframework.beans.factory.annotation.Autowired(required=true)

控制器:

@Slf4j
@RestController
@RequestMapping(value = VERSION, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public class FleetController 
public static final String VERSION = "1.0";

@Autowired
private ContactUsService service;

@InitBinder
public void initBinder(final WebDataBinder webDataBinder) 
    webDataBinder.registerCustomEditor(NatureOfEnquiryEnum.class, new  NatureOfEnquiryEnumConverter());
    webDataBinder.registerCustomEditor(FleetSizeEnum.class, new  FleetSizeEnumConverter());


@PostMapping(value = "/fleet/contact-us")
public ResponseEntity contactUs(@Valid ContactUsDTO formDTO) 
    service.createForm(formDTO);
    return new ResponseEntity(HttpStatus.NO_CONTENT);


@PostMapping(value = "/fleet/request-demo")
public ResponseEntity requestDemo(@Valid RequestDemoDTO demoDTO) 



    return new ResponseEntity(HttpStatus.NO_CONTENT);

服务:

@Service
public class ContactUsServiceImpl implements ContactUsService 

@Autowired
private FleetRepository repository;

@Override
public void createForm(ContactUsDTO formDTO) 
    ContactUsForm form = populateContactUsForm(formDTO);
    repository.save(form);

测试类:

@RunWith(JUnitPlatform.class)
@WebMvcTest(FleetController.class)
@ExtendWith(SpringExtension.class)
public class FleetControllerTest 

private final String CONTACT_US_URL = "/fleet/contact-us";

@Autowired
private MockMvc mockMvc;

@MockBean
private FleetRepository repository;

@Autowired
private ContactUsService service;


@Test
public void contactUsSuccessTest() throws Exception 
    this.mockMvc.perform( post("/" + VERSION + CONTACT_US_URL)
                    .contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
                    .param("firstname", "John")
                    .param("lastname", "Doe")
                    .param("company", "Skynet")
                    .param("emailAddress", "john.connor@sky.net")
                    .param("telephone", "020 8759 4294")
                    .param("natureOfEnquiry", "new")
                    .param("comments", "some comments")
                    .param("recaptchaResponse", "success"))
            .andExpect(status().isNoContent());


@Test
public void contactUsMissingRequiredFieldsTest() throws Exception 
    this.mockMvc.perform( post("/1.0/fleet/contact-us")
            .contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE))
            .andExpect(status().isBadRequest());

请帮忙,因为我不知道发生了什么。

【问题讨论】:

【参考方案1】:

使用 @WebMvcTest 注释的测试类是关注 Spring MVC 组件的测试:控制器。

因此,您的单元测试中声明的服务字段无法自动装配:

@Autowired
private ContactUsService service;

所以你也应该模拟这个依赖:

@MockBean
private ContactUsService service;

还要注意,由于FleetController 没有任何直接依赖于FleetRepository,因此不需要模拟此 bean:

@MockBean
private FleetRepository repository;

更糟糕的是,它会在上下文中添加一个模拟,这可能会在您的测试期间产生副作用。您必须只模拟被测控制器的直接依赖关系。


如果您只想模拟一些 bean 而不是所有不是控制器的 bean,请不要使用 @WebMvcTest 而不是使用将加载整个上下文的 @SpringBootTest。 然后在测试类中声明你想用@MockBean模拟的类。

【讨论】:

谢谢,现在有意义了! 为什么我们不能在@WebMvcTest 下使用来自Mockito 的@Mock?我得到了同样的NoSuchBeanDefinitionException @Eric Huang 因为@Mock 是一个模拟注释。为了让它可用,您需要一个 mockito junit5 扩展,但实际上您不希望这样:您希望保留 @ExtendWith(SpringExtension.class) 以加载 spring 上下文,同时可以模拟 bean。您可以参考其他问题:***.com/questions/44200720/… @davidxxx 感谢您的回复。并且非常感谢链接..

以上是关于@WebMvcTest 测试类中的 UnsatisfiedDependencyException的主要内容,如果未能解决你的问题,请参考以下文章

如何在@WebMvcTest 测试中忽略@EnableWebSecurity 注释类

SpringBoot @WebMvcTest,自动装配 RestTemplateBuilder

使用 @WebMvcTest 测试中的 ApplicationContext 异常

@WebMVCTest中的404问题分析

在 Spring Boot 测试类上使用 @WebMvcTest 注释时出错

如何将 @WebMvcTest 用于单元测试 POST 方法?