使用PowerMockito进行单元测试的Demo Mock对于单元测试来说,能够避免上下游逻辑对单元代码带来的测试复杂性,但Mockito对静态方法、私有方法等支持不好,PowerMockito是对其的拓展,功能强大。
3799
2017-06-07
Pom依赖
<!-- powermock -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>
powermock-api-mockito
</artifactId>
<version>1.6.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>
powermock-module-junit4
</artifactId>
<version>1.6.5</version>
<scope>test</scope>
</dependency>
<!-- mock -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.8.5</version>
<scope>test</scope>
</dependency>
示例代码(带注释)
package com.nd.elearning.resume.api.service;
import static org.mockito.Mockito.*;
import java.util.ArrayList;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.alibaba.fastjson.JSONObject;
import com.nd.elearning.resume.api.service.impl.BaseInfoServiceImpl;
import com.nd.elearning.resume.api.store.po.FormCfgPo;
import com.nd.elearning.resume.sdk.vo.v1.BaseInfoVo;
import com.nd.elearning.sdk.diyform.common.NowListResult;
import com.nd.elearning.sdk.diyform.vo.BizObjectFormVo;
import com.nd.gaea.rest.security.authens.UserInfo;
import com.nd.gaea.waf.security.gaea.GaeaContext;
import nd.huayu.leaf.dao.MDao;
import nd.huayu.leaf.dao.express.Cnd;
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)//委派给SpringJUnit4ClassRunner
@PowerMockIgnore({ "javax.management.*" }) // 忽略一些mock异常
/**
* PrepareForTest模拟静态方法、私有方法等时所必须的注解,被模拟的方法所在的类必须声明在该注解中
* 并配合@RunWith(PowerMockRunner.class)使用
* 注:仅模拟普通方法时,不需要写这两个注解
* 注2:@PrepareForTest注解也可被声明到具体的Test方法上
*/
@PrepareForTest({ BaseInfoServiceImpl.class, GaeaContext.class })
public class BaseInfoServiceImplTest{
@InjectMocks // 待测试的类实例
private BaseInfoServiceImpl baseInfoService;
@Mock
private MDao mDao;
@Mock
private DiyformProxyService diyformProxyService;
@Before() // 这个方法在每个方法执行之前都会执行一遍
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testGetBaseInfo() throws Exception {
/**
* Mock监视,被监视对象为真实的类实例,随后在调用待测试类的方法时调用的也是真实对象的方法,
* spy比较类似于切面,仅通过一些点来改变行为,但并不改变原对象
*/
BaseInfoServiceImpl powerSpyBaseImpl = PowerMockito.spy(baseInfoService);
// 模拟静态方法
PowerMockito.mockStatic(GaeaContext.class);
PowerMockito.when(GaeaContext.getAppId()).thenReturn(1000L);
PowerMockito.when(GaeaContext.getUserInfo()).thenReturn(new UserInfo());
// System.out.println("n" + GaeaContext.getAppId());
// 模拟私有方法,对于spy对象需要调用doReturn替代普通的thenReturn
PowerMockito.doReturn(new JSONObject()).when(powerSpyBaseImpl, "packageInitFormData");
// 模拟普通成员方法
PowerMockito.when(this.mDao.mQuery(any(Class.class), any(Cnd.class))).thenReturn(new FormCfgPo());
PowerMockito.when(this.diyformProxyService.getFormData(anyString(), anyString()))
.thenReturn(NowListResult.of(new ArrayList<JSONObject>(), 0));
PowerMockito.when(this.diyformProxyService.addFormData(anyString(), any(JSONObject.class)))
.thenReturn(new BizObjectFormVo());
PowerMockito.when(this.diyformProxyService.getFormDataByDataId(anyString(), anyString()))
.thenReturn(new JSONObject());
BaseInfoVo vo = baseInfoService.getBaseInfo("910204");
Assert.assertNotNull(vo);
}
}