PowerMock+SpringMVC整合並測試Controller層方法


PowerMock擴展自Mockito,實現了Mockito不支持的模擬形式的單元測試。PowerMock實現了對靜態方法、構造函數、私有方法以及final方法的模擬支持,對靜態初始化過程的移除等強大的功能。(官方)

接下來,通過實例來實現對SpringMVC的Controller層的方法模擬測試。

 

一、maven引入PowerMock相應的Jar文件

 1 <dependency>  
 2   <groupId>org.powermock</groupId>  
 3   <artifactId>powermock-api-mockito</artifactId>  
 4   <version>1.6.5</version>  
 5 </dependency>  
 6   
 7 <dependency>  
 8   <groupId>org.powermock</groupId>  
 9   <artifactId>powermock-module-junit4</artifactId>  
10   <version>1.6.5</version>  
11 </dependency>  	

二、單元測試基類

 1 import org.junit.runner.RunWith;  
 2 import org.powermock.core.classloader.annotations.PowerMockIgnore;  
 3 import org.powermock.modules.junit4.PowerMockRunner;  
 4 import org.powermock.modules.junit4.PowerMockRunnerDelegate;  
 5 import org.springframework.test.context.ContextConfiguration;  
 6 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  
 7 import org.springframework.test.context.transaction.TransactionConfiguration;  
 8 import org.springframework.transaction.annotation.Transactional;  
 9   
10 @RunWith(PowerMockRunner.class)  //使用PowerMockRunner運行時  
11 @PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)  //委派給SpringJUnit4ClassRunner  
12 @ContextConfiguration (locations={"classpath:META-INF/app_config/context/context-*.xml"}) //加載配置文件  
13 @Transactional  
14 @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)  
15 @PowerMockIgnore({"javax.management.*"}) //忽略一些mock異常  
16 public class BaseJunit4 {  
17       
18 }  

 

@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class):PowerMock與Spring整合時最重要的配置

@TransactionConfiguration(transactionManager="transactionManager",defaultRollback =true): 這里的事務關聯到項目的配置文件中的事務控制器("transactionManager"),同時指定事物自動回滾(defaultRollback= true),以此對數據庫不會產生數據污染。

 

三、單元測試類

 

 1 import static org.junit.Assert.assertEquals;    
 2     
 3 import java.util.HashMap;    
 4 import java.util.Map;    
 5     
 6 import javax.annotation.Resource;    
 7     
 8 import org.junit.Before;    
 9 import org.junit.Test;    
10 import org.mockito.InjectMocks;    
11 import org.powermock.api.mockito.PowerMockito;    
12 import org.powermock.core.classloader.annotations.PrepareForTest;    
13 import org.springframework.beans.factory.annotation.Autowired;    
14 import org.springframework.mock.web.MockHttpServletRequest;    
15 import org.springframework.test.util.ReflectionTestUtils;    
16     
17 import com.asset.action.IAssetScrapHandleAction;    
18 import com.asset.controller.AssetScrapHandleController;    
19 import com.framework.core.persistence.pagination.CurrentPage;    
20   
21 @PrepareForTest({OrgUtils.class,UserUtils.class})  
22 public class ScrapAssetApplyActionImplTest extends BaseJunit4{  
23     @InjectMocks@Autowired  
24     private static AssetScrapHandleController controller;  
25       
26     @Resource(name=IAssetScrapHandleAction.ACTION_ID)  
27     private IAssetScrapHandleAction aSHAction;  
28   
29     @Before  
30     public  void befor(){  
31         //依賴注入相應的action  
32         ReflectionTestUtils.setField(controller, "assetScrapHandleAction", aSHAction);  
33     }  
34   
35     @Test  
36     public void testCreateHandleNum() {  
37         Map map = new HashMap();  
38         PowerMockito.mockStatic(OrgUtils.class);PowerMockito.mockStatic(UserUtils.class);  
39           
40         //自定義模擬靜態方法返回的對象1  
41         OrganizationBO bo = new OrganizationBO();  
42         bo.setLeavel("L0");  
43         PowerMockito.when(UserUtils.getLoginUserCom()).thenReturn(bo);  
44           
45         //自定義模擬靜態方法返回的對象2  
46         UserBO userbo = new UserBO();  
47         userbo.setOrgCode("1100");  
48         LoginUser loginUser = new LoginUser(userbo);  
49         PowerMockito.when(UserUtils.getUser()).thenReturn(loginUser);  
50           
51         //模擬請求  
52         MockHttpServletRequest request = new MockHttpServletRequest();  
53         request.setParameter("time", "2016-01-01");  
54         CurrentPage page = new CurrentPage();  
55         page.setRows(25);  
56         map = controller.getDataList(request, page);   
57         boolean actual = true;   
58         assertEquals(Integer.valueOf(map.get("total").toString())>=1, actual);   
59     }  
60 }    

 

對Controller測試時,還需要由Controller層中的Action去執行相應的業務代碼,對於Action的依賴注入就可以非常方便的使用ReflectionTestUtils.setField(controller,"assetScrapHandleAction",aSHAction)(非常重要),將aSHAction注入到controller層中的屬性名為assetScrapHandleAction中  
@PrepareForTest({OrgUtils.class,UserUtils.class}) 注解一定要放到類上,或者基類上也可以,千萬不能放到方法上。如果在方法上,會導致每執行一次test方法,都會委托SpringJUnit4ClassRunner去加載一次上下文配置,將直接導致內存耗盡。

 

 

四、Controller層代碼實例  

 

 1 @Controller("assetScrapHandleController")    
 2 @RequestMapping(value="/assetScrapHandle")    
 3 public class AssetScrapHandleController  extends BaseController  {    
 4             
 5     @Resource(name=IAssetScrapHandleAction.ACTION_ID)    
 6     private IAssetScrapHandleAction assetScrapHandleAction;    
 7         
 8     @RequestMapping("/list")    
 9     @ResponseBody    
10     public Map<String,Object> getDataList(HttpServletRequest request,CurrentPage page){    
11         Map<String, Object> map = new HashMap<String, Object>();    
12         Dto param = getParamAsDto(request);    
13         String leavel = UserUtils.getLoginUserCom().getLeavel();    
14         String orgCode = UserUtils.getUser().getUser().getOrgCode();    
15         param.put("userLeavel", leavel);    
16         param.put("orgCode", orgCode);    
17         page.setParamObject(param);    
18         CurrentPage currentPage = assetScrapHandleAction.queryForPage(page);    
19             
20         map.put("rows", currentPage.getPageItems());    
21         map.put("total", currentPage.getTotalRows());    
22             
23         return map;    
24     }    
25 }    

 

UserUtils.getLoginUserCom().getLeavel();執行時,返回“L0”  
UserUtils.getUser().getUser().getOrgCode();執行時,返回“1100”  
這些都是PowerMock的功勞!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM