一 為什么需要模擬測(cè)試單元框架
1 實(shí)際工作中會(huì)出現(xiàn)當(dāng)對(duì)某個(gè)功能單元測(cè)試時(shí),需要依賴其他服務(wù),而這些服務(wù)例如第三方接口(發(fā)短信接口,支付接口),中間件(redis,消息隊(duì)列,數(shù)據(jù)庫(kù)等),微服務(wù)架構(gòu)項(xiàng)目服務(wù)間相互依賴。當(dāng)碰到依賴不能用或用依賴服務(wù)需要消耗大量資源時(shí),使用模擬測(cè)試框架輕松解決,解決思路是構(gòu)建服務(wù)返回結(jié)果,再執(zhí)行完整的功能,斷言實(shí)際結(jié)果與期望的。
2 使用單元測(cè)試框架,降低bug的出現(xiàn),提前發(fā)現(xiàn)問(wèn)題。工作中要養(yǎng)成這種良好的習(xí)慣。
二 常用的單元模擬測(cè)試框架Mockito、Jmock、easyMock。這次介紹能夠在實(shí)際中解決更多問(wèn)題的PowerMock。
三 PowerMock簡(jiǎn)介
官網(wǎng)簡(jiǎn)介 PowerMock 是一個(gè)框架,它擴(kuò)展了其他模擬庫(kù),例如具有更強(qiáng)大的功能的 EasyMock。PowerMock 使用自定義類加載器和字節(jié)碼操作來(lái)模擬靜態(tài)方法、構(gòu)造函數(shù)、最終類和方法、私有方法、靜態(tài)初始化器的刪除等。通過(guò)使用自定義類加載器,無(wú)需對(duì) IDE 或持續(xù)集成服務(wù)器進(jìn)行任何更改,從而簡(jiǎn)化了采用。熟悉受支持的模擬框架的開(kāi)發(fā)人員會(huì)發(fā)現(xiàn) PowerMock 易于使用,因?yàn)檎麄€(gè)預(yù)期 API 是相同的,無(wú)論是靜態(tài)方法還是構(gòu)造函數(shù)。PowerMock 旨在使用少量方法和注釋擴(kuò)展現(xiàn)有 API,已啟用額外功能。目前 PowerMock 支持 EasyMock 和 Mockito。
個(gè)人理解 PowerMock是為了解決現(xiàn)有的一些測(cè)試框架不能解決的問(wèn)題,PowerMock可以對(duì)final修飾的類和方法,靜態(tài)屬性和方法,私有屬性和方法進(jìn)行測(cè)試。其他框架如EasyMock和Mockito目前是沒(méi)有這些功能。
四 PowerMock優(yōu)勢(shì)
1 PowerMock 易于使用。
2 更全面地進(jìn)行單元測(cè)試。
3 簡(jiǎn)單模擬一些復(fù)雜的依賴。
五 開(kāi)啟PowerMock入門(mén)介紹
1 下面的demo用到j(luò)ar依賴如下
? ?<dependency>
? ? <groupId>org.powermock</groupId>
? ? <artifactId>powermock-module-junit4</artifactId>
? ? <version>1.7.4</version>
? ? <scope>test</scope>
</dependency>
<dependency>
? ? <groupId>org.powermock</groupId>
? ? <artifactId>powermock-api-mockito2</artifactId>
? ? <version>1.7.4</version>
? ? <scope>test</scope>
</dependency>
2 被測(cè)試類如下
? ?public class OrderDao {
? ? public int save(){
? ? ? ? throw new RuntimeException("數(shù)據(jù)連接不上了");
? ? }
}
public class OrderService {
? ? private? OrderDao orderDao;
? ? public OrderService(OrderDao orderDao) {
? ? ? ? this.orderDao = orderDao;
? ? }
? ? public int save(){
? ? ? orderDao.save();
? ? ? return 1;
? }
}
3 測(cè)試類如下。
3.1 當(dāng)運(yùn)行時(shí)測(cè)試是拋異常中斷執(zhí)行,實(shí)際工作中經(jīng)常碰到。有時(shí)需要比較長(zhǎng)時(shí)間才能恢復(fù)。那么此時(shí)用powerMock就可以快速解決,模擬數(shù)據(jù)庫(kù)數(shù)據(jù)返回,請(qǐng)看3.2。
package powerMock;
import org.junit.Test;
public class TestOrderService {
? @Test
? public void testSave(){
? ? ? OrderDao orderDao= new OrderDao();
? ? ? OrderService? orderService=new OrderService(orderDao);
? ? ? orderService.save();
? }
}
3.2 使用powerMock構(gòu)建出OrderDao實(shí)例,指定返回值,其實(shí)就是繞過(guò)數(shù)據(jù)庫(kù),構(gòu)造成功執(zhí)行結(jié)果, 再運(yùn)行測(cè)試通過(guò)。
package powerMock;
import org.junit.Test;
import org.powermock.api.mockito.PowerMockito;
import static org.junit.Assert.assertEquals;
public class TestOrderService {
? @Test
? public void testSave(){
? ? ? OrderDao orderDao= new OrderDao();
? ? ? OrderService? orderService=new OrderService(orderDao);
? ? ? orderService.save();
? }
? ? @Test
? ? public void testSaveForPowerMock(){
? ? ? ? OrderDao orderDao=PowerMockito.mock(OrderDao.class);
? ? ? ? PowerMockito.when(orderDao.save()).thenReturn(11);
? ? ? ? OrderService? orderService=new OrderService(orderDao);
? ? ? ? int total=orderService.save();
? ? ? ? assertEquals(11, total);
? ? }
}