使用PowerMockito进行单元测试的Demo Mock对于单元测试来说,能够避免上下游逻辑对单元代码带来的测试复杂性,但Mockito对静态方法、私有方法等支持不好,PowerMockito是对其的拓展,功能强大。

Pom依赖

  1. <!-- powermock -->
  2. <dependency>
  3. <groupId>org.powermock</groupId>
  4. <artifactId>
  5. powermock-api-mockito
  6. </artifactId>
  7. <version>1.6.5</version>
  8. <scope>test</scope>
  9. </dependency>
  10. <dependency>
  11. <groupId>org.powermock</groupId>
  12. <artifactId>
  13. powermock-module-junit4
  14. </artifactId>
  15. <version>1.6.5</version>
  16. <scope>test</scope>
  17. </dependency>
  18. <!-- mock -->
  19. <dependency>
  20. <groupId>org.mockito</groupId>
  21. <artifactId>mockito-all</artifactId>
  22. <version>1.8.5</version>
  23. <scope>test</scope>
  24. </dependency>

示例代码(带注释)

  1. package com.nd.elearning.resume.api.service;
  2. import static org.mockito.Mockito.*;
  3. import java.util.ArrayList;
  4. import org.junit.Assert;
  5. import org.junit.Before;
  6. import org.junit.Test;
  7. import org.junit.runner.RunWith;
  8. import org.mockito.InjectMocks;
  9. import org.mockito.Mock;
  10. import org.mockito.MockitoAnnotations;
  11. import org.powermock.api.mockito.PowerMockito;
  12. import org.powermock.core.classloader.annotations.PowerMockIgnore;
  13. import org.powermock.core.classloader.annotations.PrepareForTest;
  14. import org.powermock.modules.junit4.PowerMockRunner;
  15. import org.powermock.modules.junit4.PowerMockRunnerDelegate;
  16. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  17. import com.alibaba.fastjson.JSONObject;
  18. import com.nd.elearning.resume.api.service.impl.BaseInfoServiceImpl;
  19. import com.nd.elearning.resume.api.store.po.FormCfgPo;
  20. import com.nd.elearning.resume.sdk.vo.v1.BaseInfoVo;
  21. import com.nd.elearning.sdk.diyform.common.NowListResult;
  22. import com.nd.elearning.sdk.diyform.vo.BizObjectFormVo;
  23. import com.nd.gaea.rest.security.authens.UserInfo;
  24. import com.nd.gaea.waf.security.gaea.GaeaContext;
  25. import nd.huayu.leaf.dao.MDao;
  26. import nd.huayu.leaf.dao.express.Cnd;
  27. @RunWith(PowerMockRunner.class)
  28. @PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)//委派给SpringJUnit4ClassRunner
  29. @PowerMockIgnore({ "javax.management.*" }) // 忽略一些mock异常
  30. /**
  31. * PrepareForTest模拟静态方法、私有方法等时所必须的注解,被模拟的方法所在的类必须声明在该注解中
  32. * 并配合@RunWith(PowerMockRunner.class)使用
  33. * 注:仅模拟普通方法时,不需要写这两个注解
  34. * 注2:@PrepareForTest注解也可被声明到具体的Test方法上
  35. */
  36. @PrepareForTest({ BaseInfoServiceImpl.class, GaeaContext.class })
  37. public class BaseInfoServiceImplTest{
  38. @InjectMocks // 待测试的类实例
  39. private BaseInfoServiceImpl baseInfoService;
  40. @Mock
  41. private MDao mDao;
  42. @Mock
  43. private DiyformProxyService diyformProxyService;
  44. @Before() // 这个方法在每个方法执行之前都会执行一遍
  45. public void setup() {
  46. MockitoAnnotations.initMocks(this);
  47. }
  48. @Test
  49. public void testGetBaseInfo() throws Exception {
  50. /**
  51. * Mock监视,被监视对象为真实的类实例,随后在调用待测试类的方法时调用的也是真实对象的方法,
  52. * spy比较类似于切面,仅通过一些点来改变行为,但并不改变原对象
  53. */
  54. BaseInfoServiceImpl powerSpyBaseImpl = PowerMockito.spy(baseInfoService);
  55. // 模拟静态方法
  56. PowerMockito.mockStatic(GaeaContext.class);
  57. PowerMockito.when(GaeaContext.getAppId()).thenReturn(1000L);
  58. PowerMockito.when(GaeaContext.getUserInfo()).thenReturn(new UserInfo());
  59. // System.out.println("n" + GaeaContext.getAppId());
  60. // 模拟私有方法,对于spy对象需要调用doReturn替代普通的thenReturn
  61. PowerMockito.doReturn(new JSONObject()).when(powerSpyBaseImpl, "packageInitFormData");
  62. // 模拟普通成员方法
  63. PowerMockito.when(this.mDao.mQuery(any(Class.class), any(Cnd.class))).thenReturn(new FormCfgPo());
  64. PowerMockito.when(this.diyformProxyService.getFormData(anyString(), anyString()))
  65. .thenReturn(NowListResult.of(new ArrayList<JSONObject>(), 0));
  66. PowerMockito.when(this.diyformProxyService.addFormData(anyString(), any(JSONObject.class)))
  67. .thenReturn(new BizObjectFormVo());
  68. PowerMockito.when(this.diyformProxyService.getFormDataByDataId(anyString(), anyString()))
  69. .thenReturn(new JSONObject());
  70. BaseInfoVo vo = baseInfoService.getBaseInfo("910204");
  71. Assert.assertNotNull(vo);
  72. }
  73. }