zoukankan      html  css  js  c++  java
  • Spring+Junit+Mock测试web项目,即Controller

    准备:Maven依赖

     1 <!-- Spring和MVC的包这里不列出来了,webmvc,aspects,orm,其他maven会自动导 -->
     2 <dependency>  
     3             <groupId>junit</groupId>  
     4             <artifactId>junit</artifactId>  
     5             <version>4.9</version>  
     6             <scope>test</scope>  
     7 </dependency>   
     8 <dependency>  
     9             <groupId>org.springframework</groupId>  
    10             <artifactId>spring-test</artifactId>  
    11             <version> 4.1.3.RELEASE</version>  
    12             <scope>provided</scope>  
    13 </dependency>

    1、控制器例子

     1 package henu.controller;
     2 
     3 import org.springframework.stereotype.Controller;
     4 import org.springframework.web.bind.annotation.RequestMapping;
     5 import org.springframework.web.bind.annotation.ResponseBody;
     6 
     7 import henu.entity.Exam;
     8 
     9 /**
    10  * @ClassName: MockTestController <br/> 
    11  * @Describtion: Mock框架测试用例. <br/> 
    12  * @date: 2018年4月19日 下午2:02:47 <br/> 
    13  * @author Beats <br/> 
    14  * @version v1.0
    15  */
    16 @Controller
    17 public class MockTestController {
    18 
    19     @RequestMapping("/hello")
    20     @ResponseBody
    21     public String hello(String hello) {
    22         return hello + " world!";
    23     }
    24     
    25     @RequestMapping("/json")
    26     @ResponseBody
    27     public Exam json(String json) {
    28         Exam e = new Exam();
    29         e.setId(123);
    30         e.setSubject(json);
    31         return e;
    32     }
       }

    2、测试例子

      1 package henu.test;
      2 
      3 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.fileUpload;
      4 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
      5 import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
      6 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
      7 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
      8 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
      9 
     10 import javax.annotation.Resource;
     11 
     12 import org.junit.Before;
     13 import org.junit.Test;
     14 import org.junit.runner.RunWith;
     15 import org.springframework.http.MediaType;
     16 import org.springframework.test.context.ContextConfiguration;
     17 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
     18 import org.springframework.test.context.transaction.TransactionConfiguration;
     19 import org.springframework.test.context.web.WebAppConfiguration;
     20 import org.springframework.test.web.servlet.MockMvc;
     21 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
     22 import org.springframework.transaction.annotation.Transactional;
     23 import org.springframework.web.context.WebApplicationContext;
     24 
     25 /**
     26  * @ClassName: TestMock <br/> 
     27  * @Describtion: 使用Spring集成的Mock框架测试web应用的控制器. <br/> 
     28  * @date: 2018年4月19日 下午1:58:22 <br/> 
     29  * @author Beats <br/> 
     30  * @version v1.0
     31  */
     32 //这个必须使用junit4.9以上才有  
     33 @RunWith(SpringJUnit4ClassRunner.class)  
     34 //单元测试的时候真实的开启一个web服务,测试完毕就关闭
     35 @WebAppConfiguration  
     36 //配置事务的回滚,对数据库的增删改都会回滚,便于测试用例的循环利用  
     37 @TransactionConfiguration(transactionManager="txManager", defaultRollback=true)  
     38 @Transactional  
     39 @ContextConfiguration(locations={"classpath:spring.xml","classpath:springmvc.xml"})  
     40 //@ContextConfiguration(locations="classpath:spring*.xml")
     41 public class TestMock {
     42 
     43     /**
     44      * web应用的上下文
     45      */
     46     @Resource 
     47     private WebApplicationContext context;
     48     /**
     49      * Mock框架的核心类
     50      */
     51     private MockMvc mockMVC;
     52 
     53     @Before
     54     public void initMockMVC() {
     55         this.mockMVC = MockMvcBuilders.webAppContextSetup(context).build();
     56     }
     57 
     58     @Test
     59     public void testStringResult() throws Exception{
     60 
     61         String res = mockMVC.perform(get("/hello")
     62                 .param("hello", "This is my")
     63                 .contentType(MediaType.TEXT_HTML)
     64                 .accept(MediaType.TEXT_HTML))
     65                 .andExpect(status().isOk())//期望值
     66                 .andDo(print())//打印结果
     67                 .andReturn().getResponse().getContentAsString();//结果字符串
     68         System.err.println(res);
     69 
     70     }
     71 
     72     @Test
     73     public void testJsonResult() throws Exception{
     74 
     75         String res = mockMVC.perform(get("/json")
     76                 .param("json", "JAVA")
     77                 .param("hah", "hah")
     78                 //请求参数的类型
     79                 .contentType(MediaType.TEXT_HTML)
     80                 //希望服务器返回的值类型
     81                 .accept(MediaType.APPLICATION_JSON))
     82                 .andExpect(status().isOk())//期望值
     83                 .andDo(print())//打印结果
     84                 .andReturn().getResponse().getContentAsString();//结果字符串
     85         System.err.println(res);
     86     }
     87 
     88     @Test
     89     public void testModelResult() throws Exception{
     90 
     91         String res = mockMVC.perform(get("/json")
     92                 .param("json", "JAVA")
     93                 .param("hah", "hah")
     94                 //请求参数的类型
     95                 .contentType(MediaType.TEXT_HTML)
     96                 //希望服务器返回的值类型
     97                 .accept(MediaType.APPLICATION_JSON))
     98                     .andExpect(status().isOk())//期望值
     99                     .andDo(print())//打印结果
    100                     .andReturn().getResponse().getContentAsString();//结果字符串
    101         System.err.println(res);
    102     }
    103     
    104     @Test
    105     public void testOthers() throws Exception {
    106         byte[] bytes = new byte[] {1, 2};  
    107         mockMVC.perform(
    108                 fileUpload("/user/{id}/icon", 1L).file("icon", bytes)) //执行文件上传  
    109                     .andExpect(model().attribute("icon", bytes)) //验证属性相等性  
    110                     .andExpect(view().name("success")); //验证视图  
    111         
    112 //        mockMvc.perform(post("/user").param("name", "zhang")) //执行传递参数的POST请求(也可以post("/user?name=zhang"))  
    113 //        .andExpect(handler().handlerType(UserController.class)) //验证执行的控制器类型  
    114 //        .andExpect(handler().methodName("create")) //验证执行的控制器方法名  
    115 //        .andExpect(model().hasNoErrors()) //验证页面没有错误  
    116 //        .andExpect(flash().attributeExists("success")) //验证存在flash属性  
    117 //        .andExpect(view().name("redirect:/user")); //验证视图  
    118     }
    119 }

    函数解释:

    1     /**  
    2      * perform:执行一个RequestBuilder请求,会自动执行SpringMVC的流程并映射到相应的控制器执行处理;  
    3      * get:声明发送一个get请求的方法。MockHttpServletRequestBuilder get(String urlTemplate, Object... urlVariables):根据uri模板和uri变量值得到一个GET请求方式的。另外提供了其他的请求的方法,如:post、put、delete等。  
    4      * param:添加request的参数,如上面发送请求的时候带上了了pcode = root的参数。假如使用需要发送json数据格式的时将不能使用这种方式
    5      * andExpect:添加ResultMatcher验证规则,验证控制器执行完成后结果是否正确(对返回的数据进行的判断);  
    6      * andDo:添加ResultHandler结果处理器,比如调试时打印结果到控制台(对返回的数据进行的判断);  
    7      * andReturn:最后返回相应的MvcResult;然后进行自定义验证/进行下一步的异步处理(对返回的数据进行的判断)  
    8      */  
    注意上面contentType需要设置成MediaType.APPLICATION_JSON,即声明是发送“application/json”格式的数据。使用content方法,将转换的json数据放到request的body中。

    没有Mock框架怎么样?

      1.直接使用httpClient或者Okhttp 这方法各种麻烦
      2.使用Spring 提供的RestTemplate错误不好跟踪,必须开着服务器  
     

    spring开发中,可以使用Spring自带的MockMvc这个类进行Mock测试

    所谓的Mock测试,这里我举一个通俗易懂的例子,像servlet API中的HttpServletRequest对象是Tomcat容器生成的。我们无法手动的new出来,于是就有了所谓的Mock测试

    运行配置

    用到的注解:

    • RunWith(SpringJUnit4ClassRunner.class): 表示使用Spring Test组件进行单元测试;
    • WebAppConfiguration: 使用这个Annotate会在跑单元测试的时候真实的启动一个web服务,然后开始调用Controller的Rest API,待单元测试跑完之后再将web服务停掉;
    • ContextConfiguration: 指定Bean的配置文件信息,可以有多种方式,这个例子使用的是文件路径形式,如果有多个配置文件,可以将括号中的信息配置为一个字符串数组来表示;controller,component等都是使用注解,需要注解指定spring的配置文件,扫描相应的配置,将类初始化等。
    • TransactionConfiguration(transactionManager="transactionManager",defaultRollback=true)配置事务的回滚,对数据库的增删改都会回滚,便于测试用例的循环利用

    为什么要进行事务回滚:

    • 测试过程对数据库的操作,会产生脏数据,影响我们数据的正确性
    • 不方便循环测试,即假如这次我们将一个记录删除了,下次就无法再进行这个Junit测试了,因为该记录已经删除,将会报错。
    • 如果不使用事务回滚,我们需要在代码中显式的对我们的增删改数据库操作进行恢复,将多很多和测试无关的代码

    Mock全局配置

    1 mockMvc = webAppContextSetup(wac)  
    2             .defaultRequest(get("/user/1").requestAttr("default", true)) //默认请求 如果其是Mergeable类型的,会自动合并的哦mockMvc.perform中的RequestBuilder  
    3             .alwaysDo(print())  //默认每次执行请求后都做的动作  
    4             .alwaysExpect(request().attribute("default", true)) //默认每次执行后进行验证的断言  
    5             .build();  
    6       
    7     mockMvc.perform(get("/user/1"))  
    8             .andExpect(model().attributeExists("user"));
  • 相关阅读:
    前端整体流程
    django安装
    scrapy中出现[scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (302) to 如何解决
    python测试当前代理IP是否有效
    grequests模块
    scrapy中发起post请求
    post请求中的payload解决办法
    SSM配置动态数据源
    前端(十):使用redux管理数据
    前端(九):react生命周期
  • 原文地址:https://www.cnblogs.com/webyyq/p/8882510.html
Copyright © 2011-2022 走看看