powerMock
依赖
类注解
//标识使用powerMock进行单元测试 是Junit的Runner的扩展
@RunWith(PowerMockRunner.class)
//提前准备测试类的字节码文件 方便后续修改字节码
@PrepareForTest(测试类.class)
局部变量
其中UserService userService = new UserService()也可以使用mock的方式进行实例化,如下所示
UserService userService = PowerMock.mock(UserService.class)
有返回值:
UserService方法内部存在局部变量userDao
//无参构造
UserDao userDao = new UserDao()
通过mock()方法获取userDao实例对象
通过whenNew(依赖类.class).withNoArguments().thenReturn(实例对象)表明通过无参构造函数实现属性注入
(方式一)通过doReturn(期望值).when(mock实例).方法名(【有参数则写】)实现mock出的实例对象进行方法调用并指定返回期望值
(方式二)通过when(mock实例.方法名(【有参数则写】)).thenReturn()实现mock出的实例对象进行方法调用并指定返回期望值
通过assertEquals进行断言
无返回值:
通过doNothing().when(mock实例).方法名(【有参数则写】)实现mock出的实例对象进行方法调用,不返回任何值
通过Mockito.verify()判断方法是否被执行
静态方法
有返回值:
通过mockStatic(依赖类.class)获取依赖类中静态方法
通过when(依赖类.静态方法名()).thenReturn(期望值)实现依赖类中静态方法调用并返回期望值
无返回值:
通过doNothing().when(依赖类.class)实现无返回值的静态方法的调用
通过PowerMockito.verifyStatic()判断静态方法是否执行
final修饰的类
由于final修饰的类不能被继承 不能通过cglib的方式去代理子类
需要在@PrepareForTest({测试类.class,final修饰类.class})添加出字节码文件,其他步骤相似
verify使用
出现分支时
在UserService中存在分支执行不同的操作,判断出分支覆盖
通过Mockito.verify(mock实例).分支方法名(【参数有则写】)判断执行该方法
通过Mockito.verify(mock实例,Mockito.never()).分支方法名(【参数有则写】)判断永远不执行该方法
构造函数
由于参数是通过构造函数传递
使用PowerMockito.whenNew(mock类.class).withArguments(可变参数).thenReturn(mock实例)实现构造函数传参的使用。
Arguments Matcher抽象类
针对mock实例调用同一个方法传递不同参数,得到相同的返回值的情况
需要自定义一个类去继承ArgumentMatcher类,实现其matches抽象方法
在mock实例调用方法的时候,传递参数时,需要通过Matcher.argThat(自定义继承ArgumentMatcher类的实例)进行传递。标识对应matches方法的实现。
Answer接口
针对mock实例执行同一方法可以返回不同的值
在mock实例调用方法时,传递参数时需要使用Mockito.anyString()作为参数,用于获取所有参数值
然后在then中实现invocation的方法
(1)通过invocation获取参数
String arg = invocation.getArguments()[0]
(2)针对不同参数,期望得到不同返回值
(3)断言时,针对不用返回值分开进行
SPY和私有方法
访问私有方法时,需要通过spy实例对象
使用PowerMockito.mock获取实例并调用方法时,不会真正执行方法逻辑(eg:不会输出方法内的sout)
当使用spy去获取实例时,当断言满足期望值的时候,会通过mock方式去实现。但是当不满足期望的时候,会真正去执行方法逻辑