国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
基于TestNG+Mockito及自動裝配注解的Spring MVC集成測試
本文主要總結自己近期在項目中對MVC集成測試的實踐及理解,因為先前對這塊未實踐過。主要參考了官方文檔《11.3.6 Spring MVC Test Framework》這一章節(jié)內容,涉及到 Spring TestContext FrameworkTestNG Mockito 這3個測試框架,完全基于Spring自動裝配注解(@Autowired)實現,不需要定義額外的setter或構造器來注入bean,也不需要通過Mockito的@Mock和MockitoAnnotations.initMocks(this)代碼方式實現實例化,而是通過靜態(tài)工廠方法Mockito.mock(...)在XML中實現bean實例初始化。

 

廢話不多說了,看一下需要幾步就能搞定MVC Controller與Service層的集成測試。(如果你現在也正好使用Spring Test框架,可以看看下面對TestNG基類封裝的代碼,我覺得自己寫得還可以。小小贊美一下啦~)

 

1. 定義底層Service接口及實現

 

Java代碼  
  1. /** 
  2.  * User service. 
  3.  */  
  4. public interface UserService {  
  5.   
  6.     /** 
  7.      * Gets user info for specified user ID. 
  8.      *  
  9.      * @param id user ID 
  10.      * @return 
  11.      */  
  12.     User getUserInfo(long id);  
  13.       
  14.     /** 
  15.      * Updates user info. 
  16.      *  
  17.      * @param user user info 
  18.      * @return -1 means fail, 0 means success. 
  19.      */  
  20.     int updateUserInfo(User user);  
  21.   
  22. }  

 

Java代碼  
  1. /** 
  2.  * User query service. 
  3.  */  
  4. public interface UserQueryService {  
  5.   
  6.     /** 
  7.      * Gets user name for specified user ID. 
  8.      *  
  9.      * @param userId user ID 
  10.      * @return 
  11.      */  
  12.     String getUserName(long userId);  
  13.       
  14.     /** 
  15.      * Updates user name for specified user ID. 
  16.      *  
  17.      * @param userId 
  18.      * @param userName 
  19.      * @return -1 means fail, 0 means success. 
  20.      */  
  21.     int updateUserName(long userId, String userName);  
  22.   
  23. }  

 

Java代碼  
  1. /** 
  2.  * User query service implementation. 
  3.  */  
  4. @Service  
  5. public class UserQueryServiceImpl implements UserQueryService {  
  6.   
  7.     @Autowired  
  8.     private UserService userService;  
  9.   
  10.     @Override  
  11.     public String getUserName(long userId) {  
  12.         User user = this.userService.getUserInfo(userId);  
  13.         return user != null ? user.getName() : "";  
  14.     }  
  15.   
  16.     @Override  
  17.     public int updateUserName(long userId, String userName) {  
  18.         User user = new User(userId, userName);  
  19.         int udpateResult = this.userService.updateUserInfo(user);  
  20.         return udpateResult;  
  21.     }  
  22.   
  23. }  

 

 

2. 為 Controller 層的每一接口定義一對 Request與Response(可重用的,就別多定義啦!~\(≧▽≦)/~)

Java代碼  
  1. /** 
  2.  * Base request info. 
  3.  * 
  4.  * @author  Bert Lee 
  5.  * @version 2014-8-19 
  6.  */  
  7. @JsonIgnoreProperties(ignoreUnknown = true) // 忽略多傳的參數  
  8. public class BaseRequest {  
  9.   
  10. }  

 

Java代碼  
  1. /** 
  2.  * User ID request info. 
  3.  * 
  4.  * @author  Bert Lee 
  5.  * @version 2014-8-19 
  6.  */  
  7. public class UserIDRequest extends BaseRequest {  
  8.   
  9.     @JsonProperty("id")  
  10.     @NotNull(message = "id param is null")  
  11.     @Min(value = 1, message = "id param must be great or equal than \\{{value}\\}") // 4.3. Message interpolation -《JSR 303: Bean Validation》  
  12.     protected long id;  
  13.   
  14.     public long getId() {  
  15.         return id;  
  16.     }  
  17.   
  18.     public void setId(long id) {  
  19.         this.id = id;  
  20.     }  
  21.   
  22.     @Override  
  23.     public String toString() {  
  24.         return "UserIDRequest [id=" + id + "]";  
  25.     }  
  26.   
  27. }  

 

Java代碼  
  1. /** 
  2.  * User name response info. 
  3.  */  
  4. public class UserNameResponse {  
  5.   
  6.     @JsonProperty("name")  
  7.     protected String name = "";  
  8.   
  9.     public String getName() {  
  10.         return name;  
  11.     }  
  12.   
  13.     public void setName(String name) {  
  14.         this.name = name;  
  15.     }  
  16.   
  17.     @Override  
  18.     public String toString() {  
  19.         return "UserNameResponse [name=" + name + "]";  
  20.     }  
  21.   
  22. }  

 

Java代碼  
  1. /** 
  2.  * User info request info. 
  3.  */  
  4. public class UserInfoRequest extends UserIDRequest {  
  5.   
  6.     @JsonProperty("name")  
  7.     @NotNull(message = "name param is null")  
  8.     @Size(min = 1, message = "name param is empty")  
  9.     protected String userName; // 變量名與請求參數名不一樣,在@RequestBody中用到  
  10.   
  11.     public String getUserName() {  
  12.         return userName;  
  13.     }  
  14.   
  15.     public void setUserName(String userName) {  
  16.         this.userName = userName;  
  17.     }  
  18.   
  19.     @Override  
  20.     public String toString() {  
  21.         return "UserInfoRequest [userName=" + userName + ", id=" + id + "]";  
  22.     }  
  23.   
  24. }  

 

Java代碼  
  1. /** 
  2.  * User modify result response info. 
  3.  */  
  4. public class UserResultResponse {  
  5.   
  6.     @JsonProperty("ret")  
  7.     protected int result;  
  8.       
  9.     @JsonProperty("ret_msg")  
  10.     protected String resultMessage;  
  11.   
  12.     public UserResultResponse() {  
  13.         this.result = 0;  
  14.         this.resultMessage = "ok";  
  15.     }  
  16.   
  17.     public int getResult() {  
  18.         return result;  
  19.     }  
  20.   
  21.     public void setResult(int result) {  
  22.         this.result = result;  
  23.     }  
  24.   
  25.     public String getResultMessage() {  
  26.         return resultMessage;  
  27.     }  
  28.   
  29.     public void setResultMessage(String resultMessage) {  
  30.         this.resultMessage = resultMessage;  
  31.     }  
  32.   
  33.     @Override  
  34.     public String toString() {  
  35.         return "UserResultResponse [result=" + result + ", resultMessage="  
  36.                 + resultMessage + "]";  
  37.     }  
  38.   
  39. }  

 

 

3. 實現 Controller 層邏輯

Java代碼  
  1. /** 
  2.  * User Controller. 
  3.  * 
  4.  * @author  Bert Lee 
  5.  * @version 2014-8-19 
  6.  */  
  7. @Controller  
  8. @RequestMapping(value = "/user")  
  9. public class UserController {  
  10.   
  11.     @Autowired  
  12.     private UserQueryService userQueryService;  
  13.       
  14.       
  15.     @RequestMapping(value = "/get_user_name", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)  
  16.     @ResponseBody  
  17.     public UserNameResponse getUserName(@Valid UserIDRequest userIDRequest) {  
  18.         long userId = userIDRequest.getId();  
  19.         String userName = this.userQueryService.getUserName(userId);  
  20.           
  21.         UserNameResponse response = new UserNameResponse();  
  22.         if (!StringUtils.isEmpty(userName)) {  
  23.             response.setName(userName);  
  24.         }  
  25.           
  26.         return response;  
  27.     }  
  28.       
  29.     @RequestMapping(value = "/update_user_name", method = RequestMethod.POST,  
  30.             consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)  
  31.     @ResponseBody  
  32.     public UserResultResponse updateUserName(@Valid @RequestBody UserInfoRequest userInfoRequest) { // JSON request body map  
  33.         UserResultResponse response = new UserResultResponse();  
  34.           
  35.         long userId = userInfoRequest.getId();  
  36.         String userName = userInfoRequest.getUserName();  
  37.         int result = this.userQueryService.updateUserName(userId, userName);  
  38.         if (result < 0) {  
  39.             response.setResult(result);  
  40.             response.setResultMessage("update operation is fail");  
  41.         }  
  42.           
  43.         return response;  
  44.     }  
  45.   
  46. }  

 

 

4. 實現一個Service與Controller層的抽象測試基類(用于集成TestNG與MVC Test框架,且自動加載配置文件)

Java代碼  
  1. /** 
  2.  * Abstract base test class for TestNG. 
  3.  * 
  4.  * @author  Bert Lee 
  5.  * @version 2014-8-19 
  6.  */  
  7. @ContextConfiguration("classpath:META-INF/spring/test-context.xml") // 集成應用上下文并加載默認的beans XML配置  
  8. public abstract class AbstractTestNGTest extends AbstractTestNGSpringContextTests { // 集成TestNG  
  9.   
  10.     /** 
  11.      * Initializes the test context. 
  12.      */  
  13.     @BeforeSuite(alwaysRun = true)  
  14.     public void init() {  
  15. //      MockitoAnnotations.initMocks(this); // 基于Spring自動裝配注解,這里不再需要初始化  
  16.     }  
  17.   
  18. }  

 

Java代碼  
  1. /** 
  2.  * Abstract controller tier base test class for TestNG. 
  3.  * 
  4.  * @author  Bert Lee 
  5.  * @version 2014-8-19 
  6.  */  
  7. @WebAppConfiguration("src/test/java") // 集成Web應用上下文  
  8. public abstract class AbstractControllerTestNGTest extends AbstractTestNGTest {  
  9.   
  10.     /** 
  11.      * MVC mock 
  12.      */  
  13.     protected MockMvc mockMvc;  
  14.       
  15.     /** 
  16.      * Gets the tested controller. 
  17.      *  
  18.      * @return the controller that is tested 
  19.      */  
  20.     protected abstract Object getController();  
  21.       
  22.     /** 
  23.      * Setups the tested controller in MVC Mock environment. 
  24.      */  
  25.     @BeforeClass(alwaysRun = true)  
  26.     public void setup() {  
  27.         this.mockMvc = MockMvcBuilders.standaloneSetup(this.getController()).build();  
  28.     }  
  29.       
  30.     /** 
  31.      * Mocks the GET request. 
  32.      *  
  33.      * @param url 
  34.      * @param params 
  35.      * @param expectedContent 
  36.      * @throws Exception 
  37.      */  
  38.     protected void getMock(String url, Object[] params, String expectedContent) throws Exception {  
  39.         // 2. 構造GET請求  
  40.         MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders  
  41.                 .get(url, params);  
  42.           
  43.         this.jsonRequestMock(requestBuilder, expectedContent);  
  44.     }  
  45.       
  46.     /** 
  47.      * Mocks the POST request. 
  48.      *  
  49.      * @param url 
  50.      * @param paramsJson 
  51.      * @param expectedContent 
  52.      * @throws Exception 
  53.      */  
  54.     protected void postMock(String url, String paramsJson, String expectedContent) throws Exception {  
  55.         // 2. 構造POST請求  
  56.         MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders  
  57.                 .post(url)  
  58.                 .content(paramsJson) // 設置request body請求體,服務于"@RequestBody"  
  59.                 ;  
  60.           
  61.         this.jsonRequestMock(requestBuilder, expectedContent);  
  62.     }  
  63.       
  64.     /** 
  65.      * Mocks the request for "application/json;charset=UTF-8" media type (Content-Type). 
  66.      *  
  67.      * @param requestBuilder 
  68.      * @param expectedContent 
  69.      * @throws Exception 
  70.      */  
  71.     private void jsonRequestMock(MockHttpServletRequestBuilder requestBuilder, String expectedContent) throws Exception {  
  72.         // 2. 設置HTTP請求屬性  
  73.         requestBuilder.contentType(MediaType.APPLICATION_JSON)  
  74.                 .accept(MediaType.APPLICATION_JSON)  
  75.                 .characterEncoding(CharEncoding.UTF_8)  
  76.                 ;  
  77.           
  78.         // 3. 定義期望響應行為  
  79.         this.mockMvc.perform(requestBuilder)  
  80.                 .andDo(print()) // 打印整個請求與響應細節(jié)  
  81.                 .andExpect(status().isOk())  
  82.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))  
  83.                 .andExpect(content().string(expectedContent)) // 校驗是否是期望的結果  
  84.                 ;  
  85.     }  
  86.   
  87. }  

 

5. 實現Controller與Service層的測試邏輯

Java代碼  
  1. /** 
  2.  * Test for {@link UserController}. 
  3.  * 
  4.  * @author  Bert Lee 
  5.  * @version 2014-8-19 
  6.  */  
  7. public class UserControllerTest extends AbstractControllerTestNGTest {  
  8.   
  9.     // tested controller  
  10.     @Autowired  
  11.     private UserController userControllerTest;  
  12.       
  13.     // mocked service (被依賴的服務)  
  14.     @Autowired  
  15.     private UserQueryService userQueryService;  
  16.       
  17.       
  18.     @Test(dataProvider = "getUserName")  
  19.     public void getUserName(Object[] params, String userName, String expectedContent) throws Exception {  
  20.         // 1. 定義"被依賴的服務"的方法行為  
  21.         when(this.userQueryService.getUserName(anyLong())).thenReturn(userName);  
  22.           
  23.         this.getMock("/user/get_user_name?id={id}", params, expectedContent);  
  24.     }  
  25.     @DataProvider(name = "getUserName")  
  26.     protected static final Object[][] getUserNameTestData() {  
  27.         Object[][] testData = new Object[][] {  
  28.                 { new Object[] { "23" }, "Bert Lee", "{\"name\":\"Bert Lee\"}" },  
  29.         };  
  30.         return testData;  
  31.     }  
  32.       
  33.     @Test(dataProvider = "updateUserName")  
  34.     public void updateUserName(String paramsJson, Integer result, String expectedContent) throws Exception {  
  35.         // 1. 定義"被依賴的服務"的方法行為  
  36.         when(this.userQueryService.updateUserName(anyLong(), anyString())).thenReturn(result);  
  37.           
  38.         this.postMock("/user/update_user_name", paramsJson, expectedContent);  
  39.     }  
  40.     @DataProvider(name = "updateUserName")  
  41.     protected static final Object[][] updateUserNameTestData() {  
  42.         Object[][] testData = new Object[][] {  
  43.                 { "{\"id\":23,\"name\":\"Bert Lee\"}", 0, "{\"ret\":0,\"ret_msg\":\"ok\"}" },  
  44.         };  
  45.         return testData;  
  46.     }  
  47.       
  48.     @Override  
  49.     public Object getController() {  
  50.         return this.userControllerTest;  
  51.     }  
  52.   
  53. }  

 

Java代碼  
  1. /** 
  2.  * Test for {@link UserQueryService}. 
  3.  * 
  4.  * @author  Bert Lee 
  5.  * @version 2014-7-25 
  6.  */  
  7. public class UserQueryServiceTest extends AbstractTestNGTest {  
  8.   
  9.     // tested service  
  10.     @Autowired  
  11.     private UserQueryService userQueryServiceTest;  
  12.       
  13.     // mocked service (被依賴的服務)  
  14.     @Autowired  
  15.     private UserService userService;  
  16.       
  17.       
  18.     @Test(dataProvider = "getUserName")  
  19.     public void getUserName(User user, String expected) {  
  20.         // 1. 定義"被依賴的服務"的方法行為  
  21.         when(userService.getUserInfo(anyLong())).thenReturn(user);  
  22.           
  23.         String userName = this.userQueryServiceTest.getUserName(3L);  
  24.         assertEquals(userName, expected);  
  25.     }  
  26.     @DataProvider(name = "getUserName")  
  27.     protected static final Object[][] getUserNameTestData() {  
  28.         Object[][] testData = new Object[][] {  
  29.                 { null, "" },  
  30.                 { new User(3L, ""), "" },  
  31.                 { new User(10L, "Edward Lee"), "Edward Lee" },  
  32.                 { new User(23L, "李華剛@!~#$%^&"), "李華剛@!~#$%^&" },  
  33.         };  
  34.         return testData;  
  35.     }  
  36.   
  37. }  

 

6. 定義XML bean配置文件,實現測試對象及被依賴的服務的自動注入

Xml代碼  
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.       xsi:schemaLocation="  
  5.       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd ">  
  6.   
  7.     <bean id="userControllerTest" class="com.weibo.web.UserController" />  
  8.     <!-- 被依賴的服務 -->  
  9.     <bean id="userQueryService" class="org.mockito.Mockito" factory-method="mock">  
  10.       <constructor-arg value="com.weibo.service.UserQueryService" />  
  11.     </bean>  
  12.       
  13.     <bean id="userQueryServiceTest" class="com.weibo.service.impl.UserQueryServiceImpl" />  
  14.     <!-- 被依賴的服務 -->  
  15.     <bean id="userService" class="org.mockito.Mockito" factory-method="mock">  
  16.       <constructor-arg value="com.weibo.service.UserService" />  
  17.     </bean>  
  18.       
  19. </beans>  

 

7. 運行測試用例,OK!

 

7步搞定,挺簡單的吧,O(∩_∩)O哈哈~

 

玩得開心!^_^

本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現有害或侵權內容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Struts2 ONGL表達式
微服務框架Spring Cloud介紹 Part3: Mysteam項目結構與開發(fā)用戶注冊服務
Android static靜態(tài)成員變量的使用誤區(qū)
關于Struts-JSON配置(詳解帶實例struts2的json數據支持)
Struts2 繼承ActionSupport的用處
ognl總結
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯系客服!

聯系客服