欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring测试静态方法打桩-PowerMockito及SpringBootTest结合使用

程序员文章站 2022-07-14 10:25:31
...

Mockito无法对静态方法进行Mock,如果需要Mock静态方法,需要使用到PowerMockito。

1. Maven依赖

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito</artifactId>
    <version>1.7.1</version>
</dependency>

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>1.7.1</version>
</dependency>

2. 单元测试

单元测试时,需要使用PowerMockRunner及PrepareForTest两个注解:

@RunWith(PowerMockRunner.class)
@PrepareForTest({SysCache.class})
public class ModelAssistantServiceUTTest {
    private ModelAssistantService modelAssistantService;

    private ModelAssistantDao modelAssistantDao;

    private String tenantId;
    private String deviceTypeId;

    @Before
    public void before() throws NoSuchFieldException, IllegalAccessException {
        modelAssistantService = new ModelAssistantServiceImpl();
        modelAssistantDao = MockUtil.mockField(ModelAssistantServiceImpl.class,
                modelAssistantService, "modelAssistantDao", ModelAssistantDao.class);

        this.tenantId = "158";
        this.deviceTypeId = "3000";

        // SysCache打桩
        PowerMockito.mockStatic(SysCache.class);
        PowerMockito.when(SysCache.getTargetDbCache(BDDMockito.anyLong(), BDDMockito.anyString(), BDDMockito.any()))
                .thenReturn(new TargetDB());
    }
}

如果不使用PrepareForTest,将会报以下错误:

... not prepared for test.

而使用PrepareForTest注解时,必须要使用PowerMockRunner才会生效!

3 与SpringBootTest一起使用

SpringBootTest必须要使用SpringRunner才能生效;但RunWith没有办法指定多个,可以通过PowerMockRunnerDelegate来解决这个问题:

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest(HttpRequest.class)
@SpringBootTest

单单添加了以上四个注解还是不够,在执行的时候会报以下错误:

java.lang.LinkageError: loader constraint violation: loader (instance of org/powermock/core/classloader/MockClassLoader) previously initiated loading for a different type with name "javax/management/MBeanServer"

此时需要通过PowerMockIgnore注解来解决:

@PowerMockIgnore( {"javax.management.*"})

再次执行,发现又报以下错误:

Caused by: java.security.NoSuchAlgorithmException: class configured for SSLContext: sun.security.ssl.SSLContextImpl$TLSContext not a SSLContext

需要在PowerMockIgnore再添加一个忽略项:

@PowerMockIgnore( {"javax.management.*", "javax.net.ssl.*"})

因此,最终测试类上的注解如下:

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringRunner.class)
@PowerMockIgnore( {"javax.management.*", "javax.net.ssl.*"})
@PrepareForTest(HttpRequest.class)
@SpringBootTest

这样之后测试类终于可以成功启动了。