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()); }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM