【问题标题】:Is there a way to include a spring component in a WebMvcTest有没有办法在 WebMvcTest 中包含一个弹簧组件
【发布时间】:2019-03-21 13:26:35
【问题描述】:

给定生产代码类:

@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 层”的角度来看,而不是整个上下文 - 碰巧我需要一个仅在控制器中相关/使用的组件)

因此,我的问题是:如何在 Web 测试的测试上下文中显式包含验证器之类的组件?

我的环境是javaversion "10.0.2" 2018-07-17,spring boot1.5.16.RELEASE

【问题讨论】:

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


    【解决方案1】:

    测试web层有两种方式

    首先。

    @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/

    【讨论】:

    • 是不是说上面详述的第一种方法很可能(可能取决于在 SpringBootApplication 类上找到的其他配置)启动整个 Spring 上下文(所有服务、存储库、组件等...)。第二种方法是我已经在做的——我可以使用一个假的验证器并为验证器逻辑编写单独的单元测试来覆盖实现。我还将尝试使用 WebMvcConfigurerAdapter 定义 bean - 因为我认为这些 bean 将在上下文中应用。
    【解决方案2】:

    我不建议将其作为标准做法,但如果您确实需要 Web MVC 测试中的依赖项实例(例如在遗留代码中),您可以使用 @SpyBean 注释将它们添加到 spring 上下文中。

    该类的真实方法将在测试期间被调用,如果需要,您可以像使用 @MockBean 注释的 bean 一样验证它们

    @RunWith(SpringRunner.class)
    @WebMvcTest(MyController.class)
    public class MyControllerTest {
    
        @SpyBean
        private MyValidator validator
    }
    

    【讨论】:

      【解决方案3】:

      有两种方法可以解决这个问题。

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

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

            @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/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-05
        • 1970-01-01
        • 1970-01-01
        • 2013-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-24
        相关资源
        最近更新 更多