Spring測試靜態方法打樁-PowerMockito及SpringBootTest結合使用

icarusliu81發表於2018-05-24

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

這樣之後測試類終於可以成功啟動了。

相關文章