有没有办法在WebMvcTest中包含spring组件

时间:2018-10-16 23:13:25

标签: spring-boot spring-boot-test spring-web spring-test-mvc spring-mvc-test

给出生产代码类:

@RestController
@RequiredArgsConstructor
public class MyController {

    private final MyValidator validator;

    // annotations relating to request mapping excluded for brevity 
    public void test(@Valid @RequestBody final MyParams params) {
        // do stuff
    }

    @InitBinder
    @SuppressWarnings("unused")
    protected void initBinder(final WebDataBinder binder) {
        binder.setValidator(validator);
    }
}

@Component
@RequiredArgsConstructor
public class MyValidator implements Validator {

    ...

    @Override
    public void validate(final Object target, final Errors errors) {
        // custom validation
    }
}

最后测试代码:

@RunWith(SpringRunner.class)
@WebMvcTest(MyController.class)
public class MyControllerTest {
    // tests
}

我遇到错误:

  

NoSuchBeanDefinitionException:没有类型为'MyValidator'的合格Bean:期望至少有1个有资格作为自动装配候选的Bean。依赖项注释:{}

我认为这个错误很合理。我已经将测试注释为WebMvcTest,我认为它已经排除了@Component bean。这是有意的和期望的(从我只想测试“网络层”的角度,而不是整个上下文的角度来看-碰巧我需要一个仅在控制器中相关/使用的组件)

因此,我的问题是:如何在Web测试的测试上下文中明确包含诸如验证程序之类的组件?

我的环境是Java version "10.0.2" 2018-07-17,春季启动1.5.16.RELEASE

3 个答案:

答案 0 :(得分:2)

有两种方法可以测试网络层

第一。

@RunWith(SpringRunner.class)
@SpringBootTest
public class MyControllerTest {
  @Autowired
  private MyController myController;
}
  

@SpringBootTest注解告诉Spring Boot去寻找一个   主要配置类(带有@SpringBootApplication的类   实例),然后使用它来启动Spring应用程序上下文。

     

Spring Test 支持的一个不错的功能是该应用程序   上下文在两次测试之间被缓存,因此如果您在   一个测试用例,或具有相同配置的多个测试用例,它们   仅产生一次启动应用程序的费用。你可以控制   使用@DirtiesContext批注来缓存。

第二,如果要使用@WebMvcTest(MyController.class)

@RunWith(SpringRunner.class)
@WebMvcTest(MyController.class)
public class MyControllerTest {

  @MockBean
  private MyValidator validator;

}

但是此验证器是伪造的,因此您必须对其进行自定义以进行测试。

有关更多详细信息,请参见此链接https://spring.io/guides/gs/testing-web/

答案 1 :(得分:1)

我不建议您将其推荐为标准做法,但是如果您确实需要Web MVC测试中的某个依赖实例(例如,在旧代码中),则可以使用@SpyBean批注将其添加到spring上下文中。

该类的实际方法将在测试期间被调用,您可以根据需要验证它们,类似于用@MockBean注释的bean

@RunWith(SpringRunner.class)
@WebMvcTest(MyController.class)
public class MyControllerTest {

    @SpyBean
    private MyValidator validator
}

答案 2 :(得分:1)

有两种解决方法。

  1. 使用@SpringBootTest和@AutoConfigureMvc代替@RunWith(SpringRunner.class)和@WebMvcTest。

    @SpringBootTest
    @AutoConfigureMvc
    public class MyControllerTest {
    
    }
    
  2. 创建一个@TestConfiguration类,将“ MyValidator” bean注入为:

        @RunWith(SpringRunner.class)
        @WebMvcTest(MyController.class)
        public class MyControllerTest {
           @TestConfiguration
           static class TestConfig {
              @Bean
              MyValidator getMyValidator(){
                  return new MyValidator();
              }
           }
           // tests
        }
    

    有关更多信息,请参见:https://mkyong.com/spring-boot/spring-boot-how-to-init-a-bean-for-testing/