zoukankan      html  css  js  c++  java
  • 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()); }
  • 相关阅读:
    SSH Secure File Transfer上传文件错误:encountered 1 errors during the transfer解决办法
    出现Unrecognized field "state" (class com.jt.manage.pojo.ItemCat)异常
    (error) DENIED Redis is running in protected mode because protected mode is enabled
    错误:在maven install是抛出 “1.5不支持diamond运算符,请使用source 7或更高版本以启用diamond运算符”
    Java实现POI读取Excel文件,兼容后缀名xls和xlsx
    数据库的主从复制常用Xshell命令
    Linux搭建主从数据库服务器(主从复制)
    项目数据库备份
    Entity Frameword 查询 sql func linq 对比
    jq 选择器基础及拓展
  • 原文地址:https://www.cnblogs.com/AwenDF/p/13336278.html
Copyright © 2011-2022 走看看