powerMock 集成 springboot2

阅读更多

#

PowerMock 集成 Springboot2

## 引入jar

powermock 的版本和springboot 的版本有比较严格的对应关系,安装下面这个版本对应关系测试是通过的,否则会出现很多诡异的问题,比如报栈错误等。

```xml

 

org.springframework.boot

spring-boot-starter-parent

2.1.7.RELEASE

 

 

    org.powermock

    powermock-module-junit4

    2.0.0

    test

 

 

    org.powermock

    powermock-api-mockito2

    2.0.0

    test

 

 

 

    org.springframework

    spring-test

 

 

 

    org.springframework.boot

    spring-boot-starter-test

 

```

## 启动方式

 

```

@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版本,导致的问题。

#

PowerMock 集成 Springboot2

## 引入jar

powermock 的版本和springboot 的版本有比较严格的对应关系,安装下面这个版本对应关系测试是通过的,否则会出现很多诡异的问题,比如报栈错误等。

```xml

 

org.springframework.boot

spring-boot-starter-parent

2.1.7.RELEASE

 

 

    org.powermock

    powermock-module-junit4

    2.0.0

    test

 

 

    org.powermock

    powermock-api-mockito2

    2.0.0

    test

 

 

 

    org.springframework

    spring-test

 

 

 

    org.springframework.boot

    spring-boot-starter-test

 

```

## 启动方式

 

```

@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版本,导致的问题。

 

你可能感兴趣的:(powerMock 集成 springboot2)