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>

一、控制器例子java

 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     }
   }

二、測試例子web

  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測試spring

所謂的Mock測試,這裏我舉一個通俗易懂的例子,像servlet API中的HttpServletRequest對象是Tomcat容器生成的。咱們沒法手動的new出來,因而就有了所謂的Mock測試數據庫

運行配置

用到的註解:json

  • 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"));
相關文章
相關標籤/搜索