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的功劳!

原文地址:https://www.cnblogs.com/dengshihuang/p/8178023.html