#
## 引入jar
powermock 的版本和springboot 的版本有比较严格的对应关系,安装下面这个版本对应关系测试是通过的,否则会出现很多诡异的问题,比如报栈错误等。
```xml
```
## 启动方式
```
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringRunner.class) //mark1
@SpringBootTest(classes = TestApplication.class)
//忽略这些类,不使用mock 的classloader 加载
@PowerMockIgnore({"javax.*", "com.sun.*","org.*", "sun.security.*", "java.*", "com.qb.logconfig.*"}) //mark2
@PrepareForTest(HttpClientUtil.class) //mark3
public class FaceIdMockTest {
//...
}
```
- **@PowerMockRunnerDelegate**
由于有很多属性需要注入,我们无法自己一一注入,所以必须依赖spring去注入,本应该使用@RunWith 启动SpringRunner.class 的,但是这样会导致无法在第一时间启动PowerMock 的类加载器去mock一些静态方法的类(本测试目的是mock静态方法),所以必须使用PowerMockRunner.class ,然后通过PowerMockRunnerDelegate 来委托SpringRunner.class 。
- **@PowerMockIgnore**
上说了,PowerMock会启动给自己的classloader 去加载一些类,但是有些类通过它加载会产生问题,于是需要通过此标注忽略一些包名,如果启动中出现一些 类型转换 的错误,可以考虑通过此注解ignore掉。
- **@PrepareForTest**
要mock静态方法,必须先申明需要该类到此注解。
## mock注入
- @InjectMocks
被标注此注解的属性,会通过Mock出一个对象(非spring构造),并会将标记为@Mock @Spy 的属性注入进去。
- @spy
被@spy 的对象,其内部的属性默认不会被spring注入,不过可以通过如下方式达到目的
```java
@Spy
@Autowired
AmService amService;
```
这样使用spring 构造之后,在通过Spy包装一下,然后就会amService 就不会被自动注入到@InjectMocks 的对象里去了。
## 静态方法mock
```
PowerMockito.mockStatic(HttpClientUtil.class);
HttpClientUtil util= PowerMockito.mock(HttpClientUtil.class);
PowerMockito.when(util.postContentBody(Mockito.anyString(), Mockito.any(Map.class)))
.thenAnswer(new Answer
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
return "abcd";
}
});
```
上面例子就是mock静态方法,直接返回abcd字符串
## 一些坑
- **No tests found matching**
如果不是在测试方法里写了参数这样的低级错误,那么可以debug FilterRequest这个类的 getRunner 方法,查看里面的runner ,看是否是一个错误,在这里应该属于junit 的一个bug,没有把真正的异常暴露出来,而是告诉你 No tests found matching 。
- **Failed to transform class with name mock.verifycation.FaceIdMockTest. Reason: java.io.IOException: invalid constant type: 18**
通过debug FilterRequest 类,发现此错误。此原因就是javassist的版本的问题。因为我使用了dubbo,而dubbo附带的javassist 版本是3.15.x ,覆盖了 powermock 自带依赖的3.24.0-GA版本,导致的问题。
#
## 引入jar
powermock 的版本和springboot 的版本有比较严格的对应关系,安装下面这个版本对应关系测试是通过的,否则会出现很多诡异的问题,比如报栈错误等。
```xml
```
## 启动方式
```
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringRunner.class) //mark1
@SpringBootTest(classes = TestApplication.class)
//忽略这些类,不使用mock 的classloader 加载
@PowerMockIgnore({"javax.*", "com.sun.*","org.*", "sun.security.*", "java.*", "com.qb.logconfig.*"}) //mark2
@PrepareForTest(HttpClientUtil.class) //mark3
public class FaceIdMockTest {
//...
}
```
- **@PowerMockRunnerDelegate**
由于有很多属性需要注入,我们无法自己一一注入,所以必须依赖spring去注入,本应该使用@RunWith 启动SpringRunner.class 的,但是这样会导致无法在第一时间启动PowerMock 的类加载器去mock一些静态方法的类(本测试目的是mock静态方法),所以必须使用PowerMockRunner.class ,然后通过PowerMockRunnerDelegate 来委托SpringRunner.class 。
- **@PowerMockIgnore**
上说了,PowerMock会启动给自己的classloader 去加载一些类,但是有些类通过它加载会产生问题,于是需要通过此标注忽略一些包名,如果启动中出现一些 类型转换 的错误,可以考虑通过此注解ignore掉。
- **@PrepareForTest**
要mock静态方法,必须先申明需要该类到此注解。
## mock注入
- @InjectMocks
被标注此注解的属性,会通过Mock出一个对象(非spring构造),并会将标记为@Mock @Spy 的属性注入进去。
- @spy
被@spy 的对象,其内部的属性默认不会被spring注入,不过可以通过如下方式达到目的
```java
@Spy
@Autowired
AmService amService;
```
这样使用spring 构造之后,在通过Spy包装一下,然后就会amService 就不会被自动注入到@InjectMocks 的对象里去了。
## 静态方法mock
```
PowerMockito.mockStatic(HttpClientUtil.class);
HttpClientUtil util= PowerMockito.mock(HttpClientUtil.class);
PowerMockito.when(util.postContentBody(Mockito.anyString(), Mockito.any(Map.class)))
.thenAnswer(new Answer
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
return "abcd";
}
});
```
上面例子就是mock静态方法,直接返回abcd字符串
## 一些坑
- **No tests found matching**
如果不是在测试方法里写了参数这样的低级错误,那么可以debug FilterRequest这个类的 getRunner 方法,查看里面的runner ,看是否是一个错误,在这里应该属于junit 的一个bug,没有把真正的异常暴露出来,而是告诉你 No tests found matching 。
- **Failed to transform class with name mock.verifycation.FaceIdMockTest. Reason: java.io.IOException: invalid constant type: 18**
通过debug FilterRequest 类,发现此错误。此原因就是javassist的版本的问题。因为我使用了dubbo,而dubbo附带的javassist 版本是3.15.x ,覆盖了 powermock 自带依赖的3.24.0-GA版本,导致的问题。