springboot 单测加入参数_SpringBoot Mock测试RequestBody参数并包含其他参数接口

在SpringBoot项目中,当接口参数包含@RequestBody注解的复杂对象及额外参数时,单元测试可能会遇到参数解析问题。为了解决这个问题,可以在测试配置中添加自定义的WebMvcConfigurer实现,注册过滤器以解析请求头数据到Subject对象。测试基类中利用MockMvc构建器设置过滤器,确保在Mock测试中能够正确处理接口参数,从而完成正常的接口测试。
摘要由CSDN通过智能技术生成

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

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

格式如下:

@PutMapping("/demo/update")public String update(@Valid @RequestBody DemoRO demoRO, Subject subject) {

//...

return "success";

}

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

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

@Configurationpublic class WebConfiguration implementsWebMvcConfigurer {publicWebConfiguration() {

}//...

@Beanpublic FilterRegistrationBeanglobalContextFilter() {

FilterRegistrationBean registrationBean = new FilterRegistrationBean(new GlobalContextFilter(), new ServletRegistrationBean[0]);

registrationBean.addUrlPatterns(new String[]{"/*"});

registrationBean.setOrder(-2147483548);returnregistrationBean;

}public void addArgumentResolvers(Listresolvers) {//根据函数定义的参数类型匹配传入的参数,并转换成Subject对象

resolvers.add(newSubjectHandlerMethodArgumentResolver());

}//...

}

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

public class SubjectHandlerMethodArgumentResolver implementsHandlerMethodArgumentResolver {publicSubjectHandlerMethodArgumentResolver() {

}public booleansupportsParameter(MethodParameter parameter) {return Subject.class.isAssignableFrom(parameter.getParameterType());

}public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throwsException {

//如果接口参数满足类型匹配(即 supportsParameter == true),则获取由GlobalContext管理的存储在ThreadLocal的subjectreturn GlobalContext.getSubject().orElse((Object)null);

}}

请求拦截器GlobalContextFilter

public class GlobalContextFilter extendsOncePerRequestFilter {publicGlobalContextFilter() {

}protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throwsServletException, IOException {this.resolverSubject(request);try{

filterChain.doFilter(request, response);

}finally{this.clear();

}

}private voidclear() {

GlobalContext.clear();

}//...

private voidresolverSubject(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)

@AutoConfigureMockMvcpublic classBaseTest {

@AutowiredprotectedMockMvc mockMvc;/*** web项目上下文*/@ResourceprivateWebApplicationContext webApplicationContext;

@Resourceprivate FilterRegistrationBeanglobalContextFilter;@Beforepublic voidbefore() {//获取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 extendsBaseTest {private final HttpHeaders httpHeaders = newHttpHeaders();

@Overridepublic voidbefore() {super.before();httpHeaders.add("user-Id", "100001");

}

@Testpublic void testUpdate() throwsException {

DemoRO updateRO= newDemoRO();updateRO.setName("Demo111");this.mockMvc.perform(

put("/demo/update")

.contentType(MediaType.APPLICATION_JSON_UTF8)

.headers(httpHeaders)

.content(JSON.toJSONString(updateRO))

).andDo(print());

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值