给出生产代码类:
@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
。
答案 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)
有两种解决方法。
使用@SpringBootTest和@AutoConfigureMvc代替@RunWith(SpringRunner.class)和@WebMvcTest。
@SpringBootTest
@AutoConfigureMvc
public class MyControllerTest {
}
创建一个@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/