美文网首页
Springboot使用PowerMock单元测试

Springboot使用PowerMock单元测试

作者: 哈密朵 | 来源:发表于2019-11-07 22:01 被阅读0次

常规的单元测试只需要引入springboot-test包,其会带入junit,mockito-core,spring-test

<!-- unit test -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

单元测试class如下,如果不需要起spring环境的话可以不要@SpringBootTest和@RunWith:

@SpringBootTest
@RunWith(SpringRunner.class)
public class ContractServiceTest {
    @Mock
    private IParameterService parameterService;
    @InjectMocks
    @Autowired
    private PriceServiceImpl priceService;

    @Before
    public void before() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void test1() {
        ...
    }
}

如果需要mock静态方法,需要额外引入powerMock:

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>2.0.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>2.0.0</version>
    <scope>test</scope>
</dependency>

单元测试class的注解替换为:

@RunWith(PowerMockRunner.class) // 告诉JUnit使用PowerMockRunner进行测试
@PrepareForTest({FaccAppConfig.class}) // 所有需要测试的类列在此处,适用于模拟final类或有final, private, static, native方法的类
@PowerMockIgnore({"javax.*.*", "com.sun.*", "org.xml.*", "org.apache.*"}) //为了解决使用powermock后,提示classloader错误

如果需要配合springboot来起spring环境,注解替换为:

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringRunner.class) //RunWith依然是PowerMock,那这里Delegate委托给spring
@PowerMockIgnore({"javax.*.*", "com.sun.*", "org.xml.*", "org.apache.*"})
@PrepareForTest({FaccAppConfig.class})
@SpringBootTest

于是可以用PowerMockito来mock静态方法,when表达式依然用的Mockito的api:

PowerMockito.mockStatic(FaccAppConfig.class);
Mockito.when(FaccAppConfig.getProperty(Mockito.anyString())).thenReturn("aaabbbccc");

启动@Test测试方法时报错,因为PowerMockito版本错误造成,从1.7.4升级到2.0.0即可


图片.png

运行测试方法时,因为该方法不需要spring环境所以直接执行完成,但顺带启动的spring报错:

Caused by: com.caucho.hessian4.HessianException: jar:file:/D:/work/mavenRepository/com/focustech/serialization-hessian2/1.1.0/serialization-hessian2-1.1.0.jar!/META-INF/serialization/hessian/serializers: com.caucho.hessian4.io.RemoteSerializer is invalid because it does not implement com.caucho.hessian4.io.Serializer
at com.caucho.hessian4.io.ContextSerializerFactory.initSerializerFiles(ContextSerializerFactory.java:344)
at com.caucho.hessian4.io.ContextSerializerFactory.init(ContextSerializerFactory.java:261)
at com.caucho.hessian4.io.ContextSerializerFactory.<init>(ContextSerializerFactory.java:105)
at com.caucho.hessian4.io.ContextSerializerFactory.create(ContextSerializerFactory.java:127)
at com.caucho.hessian4.io.ContextSerializerFactory.create(ContextSerializerFactory.java:125)
at com.caucho.hessian4.io.ContextSerializerFactory.create(ContextSerializerFactory.java:125)
at com.caucho.hessian4.io.ContextSerializerFactory.create(ContextSerializerFactory.java:125)
at com.caucho.hessian4.io.SerializerFactory.<init>(SerializerFactory.java:109)
at com.caucho.hessian4.io.SerializerFactory.<init>(SerializerFactory.java:102)
at com.focus.candy.rpc.protocol.serialization.HessianSerialization.<clinit>(HessianSerialization.java:29)

错误里提到hessian2在META-INF下的配置文件serializers,文件配置的实现类和Serializer接口对应不上。就是说SPI机制没对应上,在启动过程中debug关键代码:


图片.png
图片.png
图片.png

发现Serializer接口被PowerMock的JavassistMockClassLoader加载,实现类被标准的AppClassLoader加载,所以无法对应上。
想起来需要排除PowerMock尽量不让加载公共类,在@PowerMockIgnore添上hessian的路径"com.caucho.*"即可。

相关文章

网友评论

      本文标题:Springboot使用PowerMock单元测试

      本文链接:https://www.haomeiwen.com/subject/rjjbbctx.html