mock静态方法
有时候代码中需要调用工具类的某个静态函数,但是这个函数非常复杂, 或者依赖了一些其他的东西, 我们希望”屏蔽”掉这个函数调用, 而让代码能够继续运行下去, 那么可以mock掉这个函数调用.
假设, 工具类为 MyUtil.java
, 需要mock的方法为methodA()
和 methodB(Object arg1, Object arg2)
, 单元测试类为MyClassTest
.
步骤
- 首先在单元测试类
MyClassTest
上面添加注解@PrepareForTest(MyUtil.class)
, 注意不要在测试方法上面加, 可能会报错. - 在
@Before
注解的方法里面初始化mockmockStatic(MyUtil.class)
, 注意每一个包含了静态方法的类都要初始化mock. - 在测试方法里面进行mock处理.
第3步中有两种处理方式:
如果静态方法的返回值为
void
, 我们可能只想跳过这个静态方法, 可以通过以下方式mockPowerMockito.doNothing().when(MyUtil.class, "methodA");
如果静态方法有返回值, 我们可以使用
when().thReturn()
的方式:PowerMockito.when(MyUtil.class, "methodB", arg1, arg2).thenReturn("你想要返回的内容");
阻止静态初始化, 包括static{}静态代码块或者static变量的初始化
static{}静态代码块或者static变量的初始化, 在class被容器load的时候就要被执行,如果执行错误就会导致junit单元测试错误 .
解决方法如下:
@SuppressStaticInitializationFor("com.xxx.test.MyStaticClass") //阻止静态初始化
mock构造函数
有时候在我们的测试代码内部通过new
调用构造函数生成临时对象, 这样的对象无法通过在方法调用之前mock出来, 所以需要借助PowerMock
来处理.
假设, 被测试的类为MyRealClass.java
, 针对被测试类我们编写的单元测试类为MyRealClassTest.java
, 在MyRealClass.java
的某个被测试方法中调用了 new SomeClass(Object arg1, Object arg2)
来创建临时对象.
步骤
首先需要在单元测试类上
MyRealClassTest.java
使用@PrepareForTest(MyRealClass.class)
注解, 注意这里不是SomeClass.class
, 这里填的应该是调用SomeClass.class
的调用者类, 也就是MyRealClass.class
.然后通过
whenNew().withAnyArguments().thenReturn()
来mock:PowerMockito.whenNew(SomeClass.class).withAnyArguments().thenReturn("任何你想返回的对象");
注意这里, 我不想关心参数是什么, 所以使用的是
withAnyArguments()
, 其实这样特别省事儿, 可以不用构造参数对象, 用起来很爽快!如果真要去关心参数情况, 可以使用其他几种,比如
withNoArguments()
,withArguments
,withParameterTypes
.
打破封装(进阶)
翻译: Instant Mock Testing with PowerMock
封装是面向对象编程的基本原则之一. 在一个好的面向对象的设计, 我们最终会得到一些重要的私有方法, 涉及具有重要状态信息的业务操作和字段. 有时, 单独测试它们是非常重要的。接下来, 我们将学习如何编写这种情况下的测试.
例子
首先定义我们的实体类
Department
:public