powermock框架
一、为什么要用powermock?
- 能对private/static/final等方法mock
- 能mock方法中 ”new出来“的对象“
二、powermock的使用
1、 maven依赖
<dependency><groupId>org.powermock</groupId><artifactId>powermock-module-junit4</artifactId><version>2.0.0</version><scope>test</scope></dependency><dependency><groupId>org.powermock</groupId><artifactId>powermock-api-mockito2</artifactId><version>2.0.0</version><scope>test</scope></dependency>
2、springboot基础配置(测试基类)
@PreparwForeTest({被mock的静态方法})@RunWith(PowerMockRunner.class)@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)@PowerMockIgnore({"javax.net.ssl.*","javax.management.*","javax.crypto.*"})@SpringBootTestpublicclassBasePowerMock{}
3、mock对象
1)@Mock和@MockBean
- @Mock(需要MockAnotation.init(this)初始化: 完全mock一个对象
等于Mockito.mock(Object.class) - @MockBean:mock对象替换Spring容器中的同样类型的bean
2)@Spy和@SpyBean
- @Spy: 不mock,则与普通对象一样
- @SpyBean: 不mock,则与Spring中的bean一样
4、stub
1)mock目标对象的public、private、final、static方法:
目标对象
publicclassMyThread{publicvoiddoMain(){
System.out.println(doPublic());
System.out.println(doPrivate());
System.out.println(doFinal());
System.out.println(doStatic());}public StringdoPublic(){return"this is real public";}publicstatic StringdoStatic(){return"this is real private";}private StringdoPrivate(){return"this is real private";}publicfinal StringdoFinal(){return"this is real final";}}
mock方法
@RunWith(PowerMockRunner.class)@PrepareForTest({MyThread.class,Thread.class})publicclassMyThreadTest{@TestpublicvoidtestMock()throws Exception{
MyThread myThread= PowerMockito.spy(newMyThread());
PowerMockito.doReturn("this is mock public").when(myThread,"doPublic");
PowerMockito.doReturn("this is mock private").when(myThread,"doPrivate");
PowerMockito.doReturn("this is mock final").when(myThread,"doFinal");//mock 静态方法
PowerMockito.mockStatic(MyThread.class);
PowerMockito.doReturn("this is mock static").when(MyThread.class,"doStatic");
myThread.doMain();}}
结果:
注意点:
- mock静态方法,mock的是目标.class
2) mock目标对象中的方法中”new出来的对象“:
目标类
publicclassMockOutClass{publicvoiddoMain(){
MyThread myThread=newMyThread();
myThread.doMain();}}
mock类
@RunWith(PowerMockRunner.class)@PrepareForTest({MockOutClass.class,MyThread.class})publicclassMockOutClassTest{@TestpublicvoidtestMock()throws Exception{
MockOutClass mockOutClass= PowerMockito.spy(newMockOutClass());//mock new
MyThread myThread= PowerMockito.spy(newMyThread());
PowerMockito.whenNew(MyThread.class).withAnyArguments().thenReturn(myThread);//mock method
PowerMockito.doReturn("this is mockOut public").when(myThread).doPublic();
PowerMockito.doReturn("this is mock private").when(myThread,"doPrivate");
PowerMockito.doReturn("this is mock final").when(myThread,"doFinal");//mock 静态方法
PowerMockito.mockStatic(MyThread.class);
PowerMockito.doReturn("this is mock static").when(MyThread.class,"doStatic");
mockOutClass.doMain();}}
4、verify
1) 方法调用次数
- 默认一次 Mockito.verify(uploadDataToUmpService).uploadTotalCount(Mockito.anyList());
- 自定义次数:
Mockito.verify(uploadDataToUmpService,Mockito》times(2)).uploadTotalCount(Mockito.anyList());
2)断言异常
三、powermock原理探究
1.简单原理
PowerMock简单实现原理
- 当某个测试方法被注解@PrepareForTest标注以后,在运行测试用例时,会创建一个新org.powermock.core.classloader.MockClassLoader实例,然后加载该测试用例使用到的类(系统类除外)。
- PowerMock会根据你的mock要求,去修改写在注解@PrepareForTest里的class文件(当前测试类会自动加入注解中),以满足特殊的mock需求。例如:去除final方法的final标识,在静态方法的最前面加入自己的虚拟实现等。
- 如果需要mock的是系统类的final方法和静态方法,PowerMock不会直接修改系统类的class文件,而是修改调用系统类的class文件,以满足mock需求