from:從0開始,構建前後端分離應用 1. 一些基本概念 1.1 為什麼要進行單元測試?我自己的理解是 1、能夠快速發現問題。避免衍生BUG的出現 在對一些現有代碼進行修改時,或者修改現有BUG的時候。都有可能對已有的代碼產生影響,產生新的問題。那麼怎麼能避免新問題的產生呢?那就是執行回歸測試,但 ...
from:從0開始,構建前後端分離應用
1. 一些基本概念
1.1 為什麼要進行單元測試?我自己的理解是
1、能夠快速發現問題。避免衍生BUG的出現 在對一些現有代碼進行修改時,或者修改現有BUG的時候。都有可能對已有的代碼產生影響,產生新的問題。那麼怎麼能避免新問題的產生呢?那就是執行回歸測試,但如果是人工進行費時費力,測試的還不全面。況且一般在進度的壓力下,相信很少有人會因為修改一個問題而去回歸測試以前的功能。 2、前後端分離的基礎 前後端分離的前提就是前後端不互相依賴,前後端的開發是並行的。前端不可能等待後端介面開發完成後在進行頁面的開發,後端同樣也不能等待頁面出來後在開發後端功能。那麼調試就成了問題,怎麼辦?單元測試就解決了這一問題,對於後端來講,可以使用Mock的方式,模擬request請求,達到測試的目的。 3、發佈代碼的質量保證 如果項目是使用Maven管理的,那麼根據Maven對項目周期的定義,test是進行打包、部署的前提條件,也就是每次進行打包或者部署,都是經過單元測試的。那麼就從出口確保了代碼的質量,將發現BUG的時機提前,提高工作效率。1.2 什麼是Mock
1、在單元測試過程中,到處都充滿著Mock這個東西,它是什麼? Mock的英文意思就是模仿、偽裝,簡單一點兒理解,就是對測試過程中,測試用例對外部的依賴(難以構造的,或者未完成)的一個模仿,在後臺的單元測試過程中,可以將難以構造的HttpRequest請求進行Mock。 2、在百度過程中發現了JMockit、Mockito等等,這些都是什麼? JMockit和Mockito都是用於單元測試的Mock框架,在我的項目里選擇的是Mockito1.3對後臺的測試粒度
採用junit+mock+spring-test進行的測試,是對SpringMvc的一個完整的測試,測試過程會包含DispatcherServlet、數據綁定、攔截器等環節,甚至連視圖渲染都可以進行測試。是對後臺請求的一個完整測試。並且不需要啟動tomcat伺服器
2. 添加依賴
1 <dependency> 2 <groupId>junit</groupId> 3 <artifactId>junit</artifactId> 4 <version>${version.junit}</version> 5 <scope>test</scope> 6 </dependency> 7 <dependency> 8 <groupId>org.springframework</groupId> 9 <artifactId>spring-test</artifactId> 10 <version>${version.spring}</version> 11 <scope>test</scope> 12 <exclusions> 13 <exclusion> 14 <groupId>org.testng</groupId> 15 <artifactId>testng</artifactId> 16 </exclusion> 17 </exclusions> 18 </dependency> 19 <dependency> 20 <groupId>org.mockito</groupId> 21 <artifactId>mockito-all</artifactId> 22 <version>${version.mockito}</version> 23 <scope>test</scope> 24 </dependency> 25 <dependency> 26 <groupId>org.hamcrest</groupId> 27 <artifactId>hamcrest-all</artifactId> 28 <version>${version.hamcrest}</version> 29 <scope>test</scope> 30 </dependency>
版本信息
<version.mockito>1.10.19</version.mockito> <version.hamcrest>1.3</version.hamcrest> <version.junit>4.12</version.junit> <version.spring>5.0.2.RELEASE</version.spring>以上需要註意的是hamcrest是需要引入的,否則有可能會報錯,junit需要依賴它。它的作用,我們在編寫的時候往往是編寫斷言來判斷測試結果,hamcrest是對junit斷言的增強,提供更強大的匹配規則,具體參見Hamcrest官網:http://hamcrest.org/JavaHamcrest/
3. 一些註意事項
1、在編寫測試用例的時候,往往要編寫基類。@RunWith這個註解是不能寫在基類中的,否則基類也會被當成測試用例而執行。而基類中是沒有任何測試方法的,這時候junit會報錯
有一個變通的方法,@RunWith註解仍然寫在基類上,但是為基類增加@Ignore註解,這樣在執行Test的時候,就不執行基類了
2、測試代碼放在哪個路徑下,這裡一定註意,卡了我很久。我最開始的時候寫在了/project/test/路徑下,結果就是無論怎麼執行test命令,測試用例都不行,提示“no tests to run”
正確的方式應該是將測試代碼放在/project/src/test/java/路徑下
定義基類的目的,就是將公共的代碼抽象到更高的層次。這裡包括註解和代碼
4、測試過程的環節
準備測試環境,包括Spring上下文的配置、測試數據、mockMvc初始化、請求頭信息的設置、返回預期的設置等
通過MockMvc執行請求
使用斷言對結果 進行驗證
4. 具體實現
BaseTest.java:
1、定義通用註解,由於代碼中的註解都是可以繼承的,因此完全可以抽象到基類中,避免其他的測試用例重覆的聲明這些註解
註意,@Ignore是必須要添加的,否則Maven的surefire插件也會將基類當成一個測試用例來運行,而基類中是沒有任何測試方法的,結果就是報錯
2、buildResultActions方法中,定義所有請求的通用設置,header信息,及請求結果的期望值,還有對測試過程的列印。其中就使用了hamcrest判斷結果中是否包含SUCCESS信息,如果不包含就證明出錯了。另外還定義了Session信息,否則後臺會因為session中沒有用戶信息,而將請求攔截住。
1 package com.wt.test.common; 2 3 import com.google.gson.Gson; 4 import com.wt.common.security.handler.HttpSessionHandler; 5 import com.wt.common.security.model.SysUser; 6 import org.hamcrest.Matchers; 7 import org.junit.After; 8 import org.junit.Before; 9 import org.junit.Ignore; 10 import org.junit.runner.RunWith; 11 import org.slf4j.Logger; 12 import org.slf4j.LoggerFactory; 13 import org.springframework.beans.factory.annotation.Autowired; 14 import org.springframework.http.MediaType; 15 import org.springframework.test.context.ContextConfiguration; 16 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 17 import org.springframework.test.context.web.WebAppConfiguration; 18 import org.springframework.test.web.servlet.MockMvc; 19 import org.springframework.test.web.servlet.ResultActions; 20 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; 21 import org.springframework.test.web.servlet.result.MockMvcResultHandlers; 22 import org.springframework.test.web.servlet.result.MockMvcResultMatchers; 23 import org.springframework.test.web.servlet.setup.MockMvcBuilders; 24 import org.springframework.transaction.annotation.Transactional; 25 import org.springframework.web.context.WebApplicationContext; 26 27 /** 28 * @ProjectName: syInfo 29 * @Package: com.wt.com.wt.test 30 * @Description: 31 * @Author: [email protected] 32 * @CreateDate: 2018/5/19 下午5:04 33 * @Version: v1.0 34 */ 35 36 @RunWith(SpringJUnit4ClassRunner.class) 37 @ContextConfiguration(locations = {"classpath:spring.xml", "classpath:spring-mybatis.xml", "classpath:spring-redis.xml"}) 38 @WebAppConfiguration 39 @Transactional 40 @Ignore 41 public class BaseTest { 42 Logger logger = LoggerFactory.getLogger(BaseTest.class); 43 44 @Autowired 45 WebApplicationContext webApplicationContext; 46 47 protected MockMvc mockMvc; 48 49 protected SysUser loginUser; 50 51 protected Gson gson = new Gson(); 52 53 @Before 54 public void setUp() throws Exception { 55 mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); 56 loginUser = this.createLoginUser(); 57 } 58 59 60 /** 61 * 通用設置 62 * @param mhsrb 63 * @return 64 */ 65 protected ResultActions buildResultActions(MockHttpServletRequestBuilder mhsrb) { 66 mhsrb.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE) 67 .accept(MediaType.APPLICATION_JSON_UTF8_VALUE) 68 .header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36") 69 .header("X-Requested-With", "XMLHttpRequest") 70 .sessionAttr(HttpSessionHandler.Items.LOGINUSER.name(), loginUser); 71 try { 72 return mockMvc 73 .perform(mhsrb) 74 .andExpect(MockMvcResultMatchers.status().isOk()) 75 .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) 76 .andExpect(MockMvcResultMatchers.content().string(Matchers.containsString("SUCCESS"))) 77 .andDo(MockMvcResultHandlers.print()); 78 } catch (Exception e) { 79 logger.error("請求通用設置出錯",e); 80 } 81 return null; 82 } 83 84 85 private SysUser createLoginUser() { 86 SysUser sysUser = new SysUser(); 87 sysUser.setUserId("0279c9d48c774b5b825dfb6d1058a816"); 88 sysUser.setAccount("admin"); 89 sysUser.setUserName("系統超級管理員"); 90 return sysUser; 91 } 92 93 @After 94 public void tearDown() throws Exception { 95 96 } 97 98 }
測試用例:SysUserControllerTest
1、對於新增用的測試,主要是比對新增前後的表的記錄數
2、對更新用戶的測試,主要是比對更新後的用戶名與要更新的名稱是否一致
3、刪除用戶,也是比對刪除前後的記錄實現的
1 package com.wt.common.security.controller; 2 3 import com.wt.common.security.model.SysUser; 4 import com.wt.common.security.service.SysUserService; 5 import com.wt.test.common.BaseTest; 6 import org.hamcrest.Matchers; 7 import org.junit.Assert; 8 import org.junit.Test; 9 import org.springframework.beans.factory.annotation.Autowired; 10 import org.springframework.test.annotation.Rollback; 11 import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 12 13 import java.text.SimpleDateFormat; 14 import java.util.Date; 15 import java.util.List; 16 17 import static org.hamcrest.MatcherAssert.assertThat; 18 19 /** 20 * @ProjectName: syInfo 21 * @Package: com.wt.common.security.controller 22 * @Description: 23 * @Author: [email protected] 24 * @CreateDate: 2018/5/19 下午5:01 25 * @Version: v1.0 26 */ 27 public class SysUserControllerTest extends BaseTest { 28 29 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); 30 31 @Autowired 32 private SysUserService sysUserService; 33 34 private SysUser sysUser; 35 36 @Override 37 public void setUp() throws Exception { 38 super.setUp(); 39 sysUser = this.createSysUser(); 40 } 41 42 @Test 43 public void findSysUserByUserId() throws Exception { 44 } 45 46 @Test 47 @Rollback 48 public void create() throws Exception { 49 List<SysUser> sysUsers = sysUserService.selectAll(); 50 int beforCount = sysUsers.size() + 1; 51 super.buildResultActions(MockMvcRequestBuilders 52 .post("/sysUser/create") 53 .content(gson.toJson(sysUser))); 54 List<SysUser> sysUserList = sysUserService.selectAll(); 55 int afterCount = sysUserList.size(); 56 Assert.assertTrue(beforCount == afterCount); 57 } 58 59 @Test 60 public void removeUser() throws Exception { 61 List<SysUser> beforeUsers = sysUserService.selectAll(); 62 int beforCount = beforeUsers.size(); 63 String userId = ""; 64 for (SysUser sysUser : beforeUsers) { 65 if ("admin".equals(sysUser.getAccount())) { 66 continue; 67 } 68 userId = sysUser.getUserId(); 69 break; 70 } 71 72 super.buildResultActions(MockMvcRequestBuilders 73 .delete("/sysUser/{userId}", userId)).andReturn(); 74 75 List<SysUser> afterUsers = sysUserService.selectAll(); 76 int afterCount = afterUsers.size()+1; 77 assertThat(beforCount, Matchers.equalTo(afterCount)); 78 } 79 80 @Test 81 public void update() throws Exception { 82 try { 83 List<SysUser> beforeUsers = sysUserService.selectAll(); 84 SysUser forUpdate = new SysUser(); 85 String targetName = simpleDateFormat.format(new Date()); 86 87 for (SysUser sysUser : beforeUsers) { 88 if ("admin".equals(sysUser.getAccount())) { 89 continue; 90 } 91 forUpdate = sysUser; 92 break; 93 } 94 String userId = forUpdate.getUserId(); 95 forUpdate.setUserName(targetName); 96 super.buildResultActions(MockMvcRequestBuilders.put("/sysUser").content(gson.toJson(forUpdate))); 97 SysUser updatedUser = sysUserService.findById(userId,SysUser.class); 98 Assert.assertTrue(targetName.equals(updatedUser.getUserName())); 99 } catch (Exception e) { 100 e.printStackTrace(); 101 } 102 } 103 104 private SysUser createSysUser() { 105 SysUser sysUser = new SysUser(); 106 sysUser.setUserName("測試數據" + simpleDateFormat.format(new Date())); 107 sysUser.setPassword("ceshi"); 108 sysUser.setAccount(simpleDateFormat.format(new Date())); 109 sysUser.setInUse(true); 110 sysUser.setMail("[email protected]"); 111 return sysUser; 112 } 113 }
5. 具體結果
------------------------------------------------------- T E S T S ------------------------------------------------------- Running com.wt.test.common.BaseTest Tests run: 1, Failures: 0, Errors: 0, Skipped: 1, Time elapsed: 0.007 sec Running com.wt.common.security.controller.SysUserControllerTest 2018-05-21 21:02:46,563 INFO WebTestContextBootstrapper:257 - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener] 2018-05-21 21:02:46,583 INFO WebTestContextBootstrapper:184 - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@217ed35e, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@7dcf94f8, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@229f66ed, org.springframework.test.context.support.DirtiesContextTestExecutionListener@31190526, org.springframework.test.context.transaction.TransactionalTestExecutionListener@662ac478, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@6743e411] 2018-05-21 21:02:46,714 INFO XmlBeanDefinitionReader:316 - Loading XML bean definitions from class path resource [spring.xml] 2018-05-21 21:02:47,012 INFO XmlBeanDefinitionReader:316 - Loading XML bean definitions from class path resource [spring-mybatis.xml] 2018-05-21 21:02:47,058 INFO XmlBeanDefinitionReader:316 - Loading XML bean definitions from class path resource [spring-redis.xml] 2018-05-21 21:02:47,074 INFO GenericWebApplicationContext:589 - Refreshing org.springframework.web.context.support.GenericWebApplicationContext@59af0466: startup date [Mon May 21 21:02:47 CST 2018]; root of context hierarchy 2018-05-21 21:02:47,325 INFO AutowiredAnnotationBeanPostProcessor:154 - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring 2018-05-21 21:02:48,565 INFO RequestMappingHandlerMapping:549 - Mapped "{[/syslogPerformance/getData],methods=[GET]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SyslogPerformanceController.getData() 2018-05-21 21:02:48,571 INFO RequestMappingHandlerMapping:549 - Mapped "{[/sysUser],methods=[PUT]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysUserController.update(com.wt.common.security.model.SysUser) 2018-05-21 21:02:48,571 INFO RequestMappingHandlerMapping:549 - Mapped "{[/sysUser/create],methods=[POST]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysUserController.create(com.wt.common.security.model.SysUser) 2018-05-21 21:02:48,572 INFO RequestMappingHandlerMapping:549 - Mapped "{[/sysUser/login],methods=[GET]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysUserController.login(java.lang.String,java.lang.String) throws com.wt.common.security.exception.BaseSecurityException 2018-05-21 21:02:48,573 INFO RequestMappingHandlerMapping:549 - Mapped "{[/sysUser/userByUserId/{userId}],methods=[GET]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysUserController.findSysUserByUserId(java.lang.String) 2018-05-21 21:02:48,573 INFO RequestMappingHandlerMapping:549 - Mapped "{[/sysUser/{userId}],methods=[DELETE]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysUserController.removeUser(java.lang.String) 2018-05-21 21:02:48,574 INFO RequestMappingHandlerMapping:549 - Mapped "{[/sysUser/userAll],methods=[GET]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysUserController.queryAllUser() 2018-05-21 21:02:48,575 INFO RequestMappingHandlerMapping:549 - Mapped "{[/sysUser/deleteBatch],methods=[DELETE]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysUserController.removeUsers(java.util.List<java.lang.String>) 2018-05-21 21:02:48,576 INFO RequestMappingHandlerMapping:549 - Mapped "{[/sysUser/{id}],methods=[GET]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysUserController.querySysMenu(java.lang.String) 2018-05-21 21:02:48,576 INFO RequestMappingHandlerMapping:549 - Mapped "{[/sysUser/getData],methods=[GET]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysUserController.getData() 2018-05-21 21:02:48,584 INFO RequestMappingHandlerMapping:549 - Mapped "{[/sysMenu],methods=[PUT]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysMenuController.update(com.wt.common.security.model.SysMenu) 2018-05-21 21:02:48,585 INFO RequestMappingHandlerMapping:549 - Mapped "{[/sysMenu/{id}],methods=[DELETE]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysMenuController.delete(java.lang.String) 2018-05-21 21:02:48,586 INFO RequestMappingHandlerMapping:549 - Mapped "{[/sysMenu/create],methods=[POST]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysMenuController.create(com.wt.common.security.model.SysMenu) 2018-05-21 21:02:48,586 INFO RequestMappingHandlerMapping:549 - Mapped "{[/sysMenu/{id}],methods=[GET]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysMenuController.querySysMenu(java.lang.String) 2018-05-21 21:02:48,587 INFO RequestMappingHandlerMapping:549 - Mapped "{[/sysMenu/deleteBatch],methods=[DELETE]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysMenuController.deleteBatch(java.util.List<java.lang.String>) 2018-05-21 21:02:48,588 INFO RequestMappingHandlerMapping:549 - Mapped "{[/sysMenu/queryAdminMenu],methods=[GET]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysMenuController.queryAdminMenu() 2018-05-21 21:02:48,589 INFO RequestMappingHandlerMapping:549 - Mapped "{[/sysMenu/queryAll],methods=[GET]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysMenuController.queryAll() 2018-05-21 21:02:48,590 INFO RequestMappingHandlerMapping:549 - Mapped "{[/sysMenu/getData],methods=[GET]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysMenuController.getData() 2018-05-21 21:02:48,592 INFO RequestMappingHandlerMapping:549 - Mapped "{[/upload/uploadImage],methods=[POST]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.upload.controller.UploadFileController.uploadImage(org.springframework.web.multipart.MultipartFile[]) throws com.wt.common.upload.exception.UploadException 2018-05-21 21:02:48,592 INFO RequestMappingHandlerMapping:549 - Mapped "{[/upload/deleteFile/{fileId}],methods=[DELETE]}" onto public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.upload.controller.UploadFileController.deleteFile(java.lang.String) 2018-05-21 21:02:48,762 INFO RequestMappingHandlerAdapter:568 - Looking for @ControllerAdvice: org.springframework.web.context.support.GenericWebApplicationContext@59af0466: startup date [Mon May 21 21:02:47 CST 2018]; root of context hierarchy 2018-05-21 21:02:48,850 INFO RequestMappingHandlerAdapter:568 - Looking for @ControllerAdvice: org.springframework.web.context.support.GenericWebApplicationContext@59af0466: startup date [Mon May 21 21:02:47 CST 2018]; root of context hierarchy 2018-05-21 21:02:49,252 INFO DruidDataSource:928 - {dataSource-1} inited 2018-05-21 21:02:49,566 INFO TransactionContext:105 - Began transaction (1) for test context [DefaultTestContext@3ed03652 testClass = SysUserControllerTest, testInstance = com.wt.common.security.controller.SysUserControllerTest@4aedaf61, testMethod = findSysUserByUserId@SysUserControllerTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@173797f0 testClass = SysUserControllerTest, locations = '{classpath:spring.xml, classpath:spring-mybatis.xml, classpath:spring-redis.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[org.springframework.test.context.web.socket.MockServerContainerContextCustomizer@4efbca5a], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.test.context.web.WebDelegatingSmartContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]; transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@3c35c345]; rollback [true] 2018-05-21 21:02:49,579 INFO MockServletContext:438 - Initializing Spring FrameworkServlet '' 2018-05-21 21:02:49,579 INFO TestDispatcherServlet:494 - FrameworkServlet '': initialization started 2018-05-21 21:02:49,624 INFO TestDispatcherServlet:513 - FrameworkServlet '': initialization completed in 45 ms 2018-05-21 21:02:49,629 INFO TransactionContext:137 - Rolled back transaction for test context [DefaultTestContext@3ed03652 testClass = SysUserControllerTest, testInstance = com.wt.common.security.controller.SysUserControllerTest@4aedaf61, testMethod = findSysUserByUserId@SysUserControllerTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@173797f0 testClass = SysUserControllerTest, locations = '{classpath:spring.xml, classpath:spring-mybatis.xml, classpath:spring-redis.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[org.springframework.test.context.web.socket.MockServerContainerContextCustomizer@4efbca5a], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.test.context.web.WebDelegatingSmartContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]. 2018-05-21 21:02:49,632 INFO TransactionContext:105 - Began transaction (1) for test context [DefaultTestContext@3ed03652 testClass = SysUserControllerTest, testInstance = com.wt.common.security.controller.SysUserControllerTest@58496c97, testMethod = create@SysUserControllerTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@173797f0 testClass = SysUserControllerTest, locations = '{classpath:spring.xml, classpath:spring-mybatis.xml, classpath:spring-redis.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[org.springframework.test.context.web.socket.MockServerContainerContextCustomizer@4efbca5a], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.test.context.web.WebDelegatingSmartContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]; transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@3c35c345]; rollback [true] 2018-05-21 21:02:49,633 INFO MockServletContext:438 - Initializing Spring FrameworkServlet '' 2018-05-21 21:02:49,633 INFO TestDispatcherServlet:494 - FrameworkServlet '': initialization started 2018-05-21 21:02:49,635 INFO TestDispatcherServlet:513 - FrameworkServlet '': initialization completed in 1 ms 2018-05-21 21:02:49,820 INFO LoginInterceptor:63 - ⭐️{User-Agent:[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36],Protocol:[HTTP/1.1],Remote Addr:[127.0.0.1],Method:[POST],uri:[/sysUser/create],Cookie:[null],operator:[ceshi],parameters:[[{"password":"ceshi","account":"20180521210249","userName":"測試數據20180521210249","inUse":true,"mail":"[email protected]"}]]}⭐️ MockHttpServletRequest: HTTP Method = POST Request URI = /sysUser/create Parameters = {} Headers = {Content-Type=[application/json;charset=UTF-8], Accept=[application/json;charset=UTF-8], User-Agent=[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36], X-Requested-With=[XMLHttpRequest]} Body = {"password":"ceshi","account":"20180521210249","userName":"測試數據20180521210249","inUse":true,"mail":"[email protected]"} Session Attrs = {LOGINUSER=com.wt.common.security.model.SysUser@5292ceca} Handler: Type = com.wt.common.security.controller.SysUserController Method = public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysUserController.create(com.wt.common.security.model.SysUser) Async: Async started = false Async result = null Resolved Exception: Type = null ModelAndView: View name = null View = null Model = null FlashMap: Attributes = null MockHttpServletResponse: Status = 200 Error message = null Headers = {Content-Type=[application/json;charset=UTF-8]} Content type = application/json;charset=UTF-8 Body = {"errorCode":"0","message":"SUCCESS","result":null} Forwarded URL = null Redirected URL = null Cookies = [] 2018-05-21 21:02:49,907 INFO TransactionContext:137 - Rolled back transaction for test context [DefaultTestContext@3ed03652 testClass = SysUserControllerTest, testInstance = com.wt.common.security.controller.SysUserControllerTest@58496c97, testMethod = create@SysUserControllerTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@173797f0 testClass = SysUserControllerTest, locations = '{classpath:spring.xml, classpath:spring-mybatis.xml, classpath:spring-redis.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[org.springframework.test.context.web.socket.MockServerContainerContextCustomizer@4efbca5a], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.test.context.web.WebDelegatingSmartContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]. 2018-05-21 21:02:49,910 INFO TransactionContext:105 - Began transaction (1) for test context [DefaultTestContext@3ed03652 testClass = SysUserControllerTest, testInstance = com.wt.common.security.controller.SysUserControllerTest@62e93c3a, testMethod = update@SysUserControllerTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@173797f0 testClass = SysUserControllerTest, locations = '{classpath:spring.xml, classpath:spring-mybatis.xml, classpath:spring-redis.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[org.springframework.test.context.web.socket.MockServerContainerContextCustomizer@4efbca5a], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.test.context.web.WebDelegatingSmartContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]; transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@3c35c345]; rollback [true] 2018-05-21 21:02:49,911 INFO MockServletContext:438 - Initializing Spring FrameworkServlet '' 2018-05-21 21:02:49,911 INFO TestDispatcherServlet:494 - FrameworkServlet '': initialization started 2018-05-21 21:02:49,913 INFO TestDispatcherServlet:513 - FrameworkServlet '': initialization completed in 1 ms 2018-05-21 21:02:49,938 INFO LoginInterceptor:63 - ⭐️{User-Agent:[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36],Protocol:[HTTP/1.1],Remote Addr:[127.0.0.1],Method:[PUT],uri:[/sysUser],Cookie:[null],operator:[ceshi],parameters:[[{"userId":"6057e4e4da6542f2bc32de5a43096dcd","password":"zBfDDNERxyFfyPUfh5Dg4Q\u003d\u003d","account":"20180521142248","userName":"20180521210249","inUse":true,"mail":"[email protected]","creator":"099","changedBy":"099","lastUpdate":"2018-05-20","deleteFlag":false}]]}⭐️ MockHttpServletRequest: HTTP Method = PUT Request URI = /sysUser Parameters = {} Headers = {Content-Type=[application/json;charset=UTF-8], Accept=[application/json;charset=UTF-8], User-Agent=[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36], X-Requested-With=[XMLHttpRequest]} Body = {"userId":"6057e4e4da6542f2bc32de5a43096dcd","password":"zBfDDNERxyFfyPUfh5Dg4Q\u003d\u003d","account":"20180521142248","userName":"20180521210249","inUse":true,"mail":"[email protected]","creator":"099","changedBy":"099","lastUpdate":"2018-05-20","deleteFlag":false} Session Attrs = {LOGINUSER=com.wt.common.security.model.SysUser@292158f8} Handler: Type = com.wt.common.security.controller.SysUserController Method = public com.wt.common.core.result.HttpResultEntity<?> com.wt.common.security.controller.SysUserController.update(com.wt.common.security.model.SysUser) Async: Async started = false Async result = null Resolved Exception: Type = null