• SpringBoot Mock测试RequestBody参数并包含其他参数接口


    (当接口的参数用@RequestBody修饰,同时还有另外的参数的情况)

    测试接口的时候,如果项目中请求经过网关,转发到服务时,中间会将请求头数据转换成参数对象Subject。

    格式如下:

    @PutMapping("/demo/update")
    public String update(@Valid @RequestBody DemoRO demoRO, Subject subject) {
    //...
    return "success";
    }

    这时,如果使用mock测试,参数subject传递一直失败,无法解析。

    经过一番查找,将实现了解析参数的 WebMvcConfigurer的实现类WebConfiguration加到Test的基类中加载,实现了正常的接口测试

    @Configuration
    public class WebConfiguration implements WebMvcConfigurer {
    
        public WebConfiguration() {
        }
    
        //...
    @Bean public FilterRegistrationBean<GlobalContextFilter> globalContextFilter() { FilterRegistrationBean<GlobalContextFilter> registrationBean = new FilterRegistrationBean(new GlobalContextFilter(), new ServletRegistrationBean[0]); registrationBean.addUrlPatterns(new String[]{"/*"}); registrationBean.setOrder(-2147483548); return registrationBean; }
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { //根据函数定义的参数类型匹配传入的参数,并转换成Subject对象 resolvers.add(new SubjectHandlerMethodArgumentResolver()); } //... }

    请求参数与接口参数匹配类

    public class SubjectHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
        public SubjectHandlerMethodArgumentResolver() {
        }
    
        public boolean supportsParameter(MethodParameter parameter) {
            return Subject.class.isAssignableFrom(parameter.getParameterType());
        }
    
        public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    //如果接口参数满足类型匹配(即 supportsParameter == true),则获取由GlobalContext管理的存储在ThreadLocal的subject
    return GlobalContext.getSubject().orElse((Object)null); } }

    请求拦截器GlobalContextFilter 

    public class GlobalContextFilter extends OncePerRequestFilter {
    
        public GlobalContextFilter() {
        }
    
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
            this.resolverSubject(request);
            try {
                filterChain.doFilter(request, response);
            } finally {
                this.clear();
            }
        }
    
        private void clear() {
            GlobalContext.clear();
        }
    
        //...
    
        private void resolverSubject(HttpServletRequest request) {
            if (NumberUtils.isNumber(request.getHeader("user-Id"))) {
                Long id = Long.valueOf(request.getHeader("user-Id"));
                Subject subject = Subject.builder().id(id).build();
                //解析请求头,并存入封装了ThreadLocal的GlobalContext中
                GlobalContext.setSubject(subject);
            }
        }
    
    }

    测试基类

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = DemoApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
    @ContextConfiguration(classes = WebConfiguration.class, initializers= ConfigFileApplicationContextInitializer.class)
    @AutoConfigureMockMvc
    public class BaseTest {
    
        @Autowired
        protected MockMvc mockMvc;
    
        /**
         * web项目上下文
         */
        @Resource
        private WebApplicationContext webApplicationContext;
    
        @Resource
        private FilterRegistrationBean<GlobalContextFilter> globalContextFilter;
    
        @Before
        public void before() {
            //获取mockmvc对象实例
            mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
                    .addFilter(globalContextFilter.getFilter())
                    .build();
        }
    
    }

    Controller测试类

    import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
    import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;

    public
    class DemoControllerTest extends BaseTest { private final HttpHeaders httpHeaders = new HttpHeaders(); @Override public void before() { super.before(); httpHeaders.add("user-Id", "100001"); } @Test public void testUpdate() throws Exception { DemoRO updateRO = new DemoRO(); updateRO.setName("Demo111");this.mockMvc.perform( put("/demo/update") .contentType(MediaType.APPLICATION_JSON_UTF8) .headers(httpHeaders) .content(JSON.toJSONString(updateRO)) ).andDo(print()); }
  • 相关阅读:
    windows环境利用hexo+github搭建个人博客
    tf.matmul() 和tf.multiply() 的区别
    RuntimeError: Python is not installed as a framework. The Mac OS X backend will not be able to function correctly if Python is not installed as a framework. See the Python documentation for more infor
    tensorboard在Mac OS X系统环境下如何启动
    atom的使用
    PCA降维2
    PCA降维
    正态分布的介绍
    各种距离 欧式距离、曼哈顿距离、切比雪夫距离、闵可夫斯基距离、标准欧氏距离、马氏距离、余弦距离、汉明距离、杰拉德距离、相关距离、信息熵
    电脑中英文文件夹一般代表的含义 和 常见的后缀名的的意思
  • 原文地址:https://www.cnblogs.com/AwenDF/p/13336278.html
Copyright © 2020-2023  润新知