PowerMockito.mockStatic(class) 模擬靜態方法調用
爲什麼要寫單元測試
- 給我們重構的信心(give us the confidence to refactor)。一堆糾纏而無測試的代碼你敢隨便修改?
- 好的單元測試就是文檔 (documenting expected behavior)。幾個實用的例子比文檔讓人感興趣的多!
引入依賴
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.23.4</version>
<scope>test</scope>
</dependency>
<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>
模擬工具類調用靜態方法
工具類:SysDataCodeUtils
@Slf4j
public class SysDataCodeUtils {
public static String getNameByCodeAndValue(String code, String key) {
try {
List<SysDataCodeDTO> list = sysDataCodeService.getListByCode(code);
for (SysDataCodeDTO dataCodeDTO : list) {
if (dataCodeDTO.getCode().equals(key)) {
return dataCodeDTO.getValue();
}
}
} catch (Exception e) {
log.error("獲取快速編碼表異常:{}", e);
}
return StrUtil.EMPTY;
}
}
測試類:ShareProfitRefundSettleServiceImplTest
@RunWith(PowerMockRunner.class)
@PrepareForTest({ SysDataCodeUtils.class })
public class ShareProfitRefundSettleServiceImplTest {
@InjectMocks
ShareProfitRefundSettleServiceImpl shareProfitRefundSettleService = new ShareProfitRefundSettleServiceImpl();
@Mock
ClearingDao clearingDao;
@Before
public void before(){
log.info("start--------{}",this.getClass().getName());
PowerMockito.mockStatic(SysDataCodeUtils.class);
PowerMockito.when(SysDataCodeUtils.getNameByCodeAndValue("SHARE_PROFIT_REFUND_TERM", "SWITCH")).thenReturn("OPEN");
}
}
註解說明
@RunWith(MockitoJUnitRunner.class):JUnit 使用 Mockito 模擬框架提供的“單元測試運行器。
@RunWith(PowerMockRunner.class):JUnit 使用 PowerMock 框架中的單元測試運行器。
(使用這些特定於框架的測試運行程序的要點是,它們負責使用特殊的特定於框架的註釋初始化所有字段)。
因此,這裏的區別僅在於:第一個示例是使用 Mockito 框架編寫的,第二個示例是使用 PowerMock
編寫的。*如果要模擬對靜態方法的調用,需要使用 @RunWith(PowerMockRunner.class)。如果不需要模擬靜態或私有函數,最好還是使用原生 MockitoJUnitRunner 進行單測。
@PrepareForTest({ SysDataCodeUtils.class }):當使用PowerMockito.whenNew方法時,必須加註解@PrepareForTest和@RunWith。註解@PrepareForTest裏寫的類是需要mock的new對象代碼所在的類。如果有兩個不同類的靜態方法需要驗證呢,比如類A、類B,則只需要一起添加,用逗號隔開就可以了:@PrepareForTest({ A.class, B.class })。
@InjectMocks:創建一個實例,簡單的說是這個Mock可以調用真實代碼的方法,其餘用@Mock(或@Spy)註解創建的mock將被注入到用該實例中。
@Mock: 創建一個Mock。