spring boot单元测试之十一:给带有filter的controller做单元测试(spring boot 2.4.4)

一,演示项目的相关信息

1,地址:

https://github.com/liuhongdi/filtertest

2,功能:演示给带有filter的controller做单元测试

3,项目结构:如图:

说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

         对应的源码可以访问这里获取: https://github.com/liuhongdi/

说明:作者:刘宏缔 邮箱: 371125307@qq.com

二,java代码说明

1,filter/TimeFilter.java

public class TimeFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("----------------time filter init");
    }
   //过滤功能,我们统计请求所花费的时间
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("----------------time filter doFilter begin");
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String path = request.getRequestURI();
        String v = request.getParameter("v");
        System.out.println("filter: v: "+v);
        if (v == null || v.equals("")) {
            ServletUtil.printString("缺少参数");
            return;
        }
        String method = request.getMethod();
        System.out.println("filter: method: "+method);
        //if ()
        long startTime = System.currentTimeMillis();
        filterChain.doFilter(servletRequest,servletResponse);
        long endTime = System.currentTimeMillis();
        System.out.println("timefilter: "+path + " costtime: "+ (endTime-startTime) +"ms ");
        System.out.println("----------------time filter doFilter end");
    }

    @Override
    public void destroy() {
        System.out.println("----------------time filter destroy");
    }

}

2,util/ServletUtil.java

public class ServletUtil {

    //获取request
    public static HttpServletRequest getRequest() {
        return getRequestAttributes().getRequest();
    }

    //获取response
    public static HttpServletResponse getResponse() {
        return getRequestAttributes().getResponse();
    }

    //获取session
    public static HttpSession getSession() {
        return getRequest().getSession();
    }

    //获取ServletRequestAttributes
    public static ServletRequestAttributes getRequestAttributes() {
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        return (ServletRequestAttributes) attributes;
    }

    //得到当前的url地址
    public static String getUrl() {
        HttpServletRequest request= getRequestAttributes().getRequest();
        String ip = request.getRemoteAddr();
        String url = request.getRequestURL().toString();
        String param = request.getQueryString();
        //System.out.println("param:"+param);
        String finalurl = ip+"--"+url;
        if (param != null) {
            finalurl= ip+"--"+url+"?"+param;
        }
        return finalurl;
    }

    //将字符串渲染到客户端
    public static String printString(String string) {
        try {
            HttpServletResponse response= getResponse();
            response.setContentType("text/html");
            response.setCharacterEncoding("utf-8");
            //response.getWriter().print(string);
            PrintWriter out = response.getWriter();
            //response.getWriter().print(resp);
            out.write(string);
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    //判断请求是否是ajax
    public static boolean isAjax() {
        HttpServletRequest request= getRequest();
        return (request.getHeader("X-Requested-With") != null &&
                "XMLHttpRequest".equals(request.getHeader("X-Requested-With").toString()));
    }

}

3,controller/HomeController.java

@Controller
@RequestMapping("/home")
public class HomeController {

    //示例controller,供统计时间用
    @GetMapping("/home")
    @ResponseBody
    public String homeMethod(@RequestParam("v") String version) {
            System.out.println("controller v:"+version);
            try {
                Thread.sleep(1000);    //延时1秒
            }
            catch(InterruptedException e) {
                e.printStackTrace();
            }
            return "this is home,v="+version;
    }

}

4,config/DefaultMvcConfig.java

@Configuration
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class DefaultMvcConfig implements WebMvcConfigurer {


    //add filter
     //registration.addUrlPatterns("/icons/*", "/style/*", "/script/*", "/dwr/*", "/icons/*", "/coverArt.view", "/avatar.view");
    //registration.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid2/*");

    @Bean
    public FilterRegistrationBean addTimeFilterBean() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new TimeFilter());
        registration.setName("timeFilter");
        registration.setOrder(1);  //请求中过滤器执行的先后顺序,值越小越先执行
        registration.addUrlPatterns("/home/*","/abc/*");
        return registration;
    }

}

5,controller/HomeControllerTest.java

@AutoConfigureMockMvc
@SpringBootTest
class HomeControllerTest {

    @Autowired
    private HomeController homeController;

    @Autowired
    private MockMvc mockMvc;

    @Test
    @DisplayName("测试controller返回")
    void home1() throws Exception {
        MvcResult mvcResult = mockMvc.perform(get("/home/home?v=3")
                .contentType(MediaType.APPLICATION_FORM_URLENCODED))
                .andReturn();
        String content = mvcResult.getResponse().getContentAsString();
        assertThat(content, equalTo("this is home,v=3"));
    }

    @Test
    @DisplayName("测试过滤器返回")
    void home2() throws Exception {
        MvcResult mvcResult = mockMvc.perform(get("/home/home")
                .contentType(MediaType.APPLICATION_FORM_URLENCODED))
                .andReturn();
        String content = mvcResult.getResponse().getContentAsString();
        assertThat(content, equalTo("缺少参数"));
    }
}

三,测试效果

四,备注

1,如果使用了FilterRegistrationBean引入fitler,

  又同时在filter的类上加了@Component注解,

   则使用mockmvc时会导致filter被执行两次

   大家注意只使用一种引入方式

五,查看spring boot的版本:

  .   ____          _            __ _ _
 /\ / ___'_ __ _ _(_)_ __  __ _    
( ( )\___ | '_ | '_| | '_ / _` |    
 \/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.4.4)
原文地址:https://www.cnblogs.com/architectforest/p/14597432.html