日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

PowerMock 入门

發(fā)布時間:2023/12/15 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PowerMock 入门 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

    • 介紹
      • Mock測試
        • 好處-- 模擬數(shù)據(jù)
        • 好處--減少依賴
      • 包導(dǎo)入
      • 示例
    • 常用注解
      • @RunWith(PowerMockRunner.class)
      • @PrepareForTest({UserController.class})
      • @PowerMockIgnore(“javax.management.*”)
    • 常用行為錄制模式
      • when(…).thenXXX()
      • doXXX(…).when(mockObj)
    • Mock靜態(tài)方法
      • 使用方法
      • 驗證行為
      • 使用參數(shù)匹配
      • 拋出異常
        • 非私有方法
      • 私有方法
      • 示例
    • Mock Final關(guān)鍵字
      • 說明
      • 實例
    • 局部Mock
      • 說明
      • 驗證行為
        • 普通公有方法
        • 驗證私有方法
    • Mock構(gòu)造函數(shù)
      • 說明
      • 示例

介紹

PowerMock是一個Java模擬框架,用于解決測試問題。

PowerMock 由Mockito和EasyMock兩部分API構(gòu)成,它必須要依賴測試框架。

當(dāng)前PowerMock支持Junit和TestNG.兩種測試框架。

針對Junit又有三種不同的執(zhí)行器對應(yīng)JUnit4.4+、JUnit4.0-4.3和JUnit 3。

TestNG的執(zhí)行器實現(xiàn)只有一個版本,但是需要依賴TestNG5.11+版本。

Mock測試

Mock 測試就是在測試過程中,對于某些不容易構(gòu)造(如 HttpServletRequest 必須在Servlet 容器中才能構(gòu)造出來)或者不容易獲取比較復(fù)雜的對象(如 JDBC 中的ResultSet 對象),用一個虛擬的對象(Mock 對象)來創(chuàng)建以便測試的測試方法。

好處-- 模擬數(shù)據(jù)

在使用Junit進行單元測試時,不想讓測試數(shù)據(jù)進入數(shù)據(jù)庫,可以使用PowerMock,攔截數(shù)據(jù)庫操作,并模擬返回參數(shù)。

好處–減少依賴

代碼存在如下依賴:

當(dāng)需要測試A類的時候,如果沒有Mock,則需要把整個依賴樹都構(gòu)建出來,而使用Mock的話就可以將結(jié)構(gòu)分解開

包導(dǎo)入

Junit 4.4+ (不同包導(dǎo)入會有差異)

<!-- PowerMock JUnit 4.4+ Module --> <dependency><groupId>org.powermock</groupId><artifactId>powermock-module-junit4</artifactId><version>2.0.0</version><scope>test</scope> </dependency> <!-- PowerMock Mockito2 API --> <dependency><groupId>org.powermock</groupId><artifactId>powermock-api-mockito2</artifactId><version>2.0.0</version><scope>test</scope> </dependency> <dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope> </dependency>

示例

/***********************Prepare****************************/ public interface MockMapper {   public int count(MockModel model); }@Servicepublic class MockServiceImpl {   @Autowired   private MockMapper mockMapper;   public int count(MockModel model) {     return mockMapper.count(model);   } } /*****************************************************/ @RunWith(PowerMockRunner.class) // 告訴JUnit使用PowerMockRunner進行測試 @PrepareForTest({MockUtil.class}) // 所有需要測試的類列在此處,適用于模擬final類或有final, private, static, native方法的類 @PowerMockIgnore("javax.management.*") //為了解決使用powermock后,提示classloader錯誤 public class MockExample {// 將@Mock注解的示例注入進來@InjectMocksprivate MockServiceImpl mockService;@Mockprivate MockMapper mockMapper;/*** mock普通方法*/@Testpublic void testSelectAppAdvertisementList() {MockModel model = new MockModel();PowerMockito.when(mockMapper.count(model)).thenReturn(2);Assert.assertEquals(2, mockService.count(model));} }

常用注解

@RunWith(PowerMockRunner.class) // 告訴JUnit使用PowerMockRunner進行測試 @PrepareForTest({RandomUtil.class}) // 所有需要測試的類列在此處,適用于模擬final類或有final, private, static, native方法的類 @PowerMockIgnore("javax.management.*") //為了解決使用powermock后,提示classloader錯誤

@RunWith(PowerMockRunner.class)

該注解需要在測試類上添加,告訴JUnit使用PowerMock執(zhí)行器,一般來說都添加上。

@PrepareForTest({UserController.class})

所有需要測試的類,列在此處,以逗號分隔。測試靜態(tài)方法、私有方法、final方法、使用System/Bootstrap類加載器加載的類和mock構(gòu)造方法時需要添加該注解。

注意:@PrepareForTest中包含的類不會被LLT統(tǒng)計到代碼覆蓋。

@PowerMockIgnore(“javax.management.*”)

為了解決使用powermock后,提示classloader錯誤。

常用行為錄制模式

when(…).thenXXX()

doXXX(…).when(mockObj)

Mock靜態(tài)方法

使用方法

(1)在測試類上加入@RunWith(PowerMockRunner.class)(該注解告訴JUnit使用PowerMock執(zhí)行器)和@ PrepareForTest(Static.class)注解.

(2)使用PowerMock.mockStatic(Static.class)可以mock Static類中所有的靜態(tài)方法。也可以使用PowerMockito.spy(class)方法來對特定的方法mock.

(3)調(diào)用Mockito.when()來錄制行為。

驗證行為

要驗證靜態(tài)方法是否有被執(zhí)行,可以使用PowerMockito.verifyStatic(Mockito.times(1)),每驗證一個函數(shù)都需要先調(diào)用一次PowerMockito.verifyStatic(…)函數(shù):

(1)調(diào)用PowerMockito.verifyStatic()方法開始驗證行為,不傳參數(shù)默認是驗證調(diào)用一次,要校驗調(diào)用多次傳入Mockito.times(…)即可。

(2)PowerMockito.verifyStatic()之后,調(diào)用需要驗證的靜態(tài)方法即可完成驗證。

PowerMockito.verifyStatic(); // 1ClassThatContainsStaticMethod. getUserName (param); // 2

使用參數(shù)匹配

Mockito的參數(shù)匹配仍舊適用于PowerMock

PowerMockito.verifyStatic();Static.thirdStaticMethod(Mockito.anyInt());

拋出異常

非私有方法

PowerMockito.doThrow(new ArrayStoreException("Mock error")).when(StaticService.class);

私有方法

由于不能直接訪問方法,可以將方法名以字符串的形式告訴powermock進行調(diào)用

when(tested, "methodToExpect", argument).thenReturn(myReturnValue);when(tested, "methodToExpect", argument).thenThrow(new ArrayStoreException("Mock error"));

示例

類ClassThatContainsStaticMethod
存在一個靜態(tài)方法getUserName()返回一個字符串:UserName:id。

package com.cainiaoguoguo.mocktest.staticmethod;public class ClassThatContainsStaticMethod {public static String getUserName(int id){return "UserName:" + id;}}

對ClassThatContainsStaticMethod.getUserName()進行mock

package com.cainiaoguoguo.mocktest.staticmethod;import org.junit.Test;import org.junit.runner.RunWith;import org.mockito.Mockito;import org.powermock.api.mockito.PowerMockito;import org.powermock.core.classloader.annotations.PrepareForTest;import org.powermock.modules.junit4.PowerMockRunner;import static org.junit.Assert.*;@RunWith(PowerMockRunner.class)@PrepareForTest(ClassThatContainsStaticMethod.class)public class StaticMethodTest {@Testpublic void echoUserName() throws Exception {final String expectResult = "expectResult";// mock ClassThatContainsStaticMethod類中所有的靜態(tài)方法PowerMockito.mockStatic(ClassThatContainsStaticMethod.class);// 改變方法的行為,當(dāng)調(diào)用getUserName的時候返回expectResultPowerMockito.when(ClassThatContainsStaticMethod.getUserName(Mockito.anyInt())).thenReturn(expectResult);assert(ClassThatContainsStaticMethod.getUserName(123).equals(expectResult));// true}}

首先添加了@RunWith(PowerMockRunner.class)和@PrepareForTest(ClassThatContainsStaticMethod.class)兩個注解
然后調(diào)用PowerMockito.mockStatic對靜態(tài)方法進行mock
接下來調(diào)用when…then…模式對方法行為進行錄制
調(diào)用getUserName方法判斷返回結(jié)果。

綜合示例

/************************Prepare****************************/ public class MockUtil {private static final Random random = new Random();public static int nextInt(int bound) {return random.nextInt(bound);} } /***************************************************/@RunWith(PowerMockRunner.class) // 告訴JUnit使用PowerMockRunner進行測試 @PrepareForTest({MockUtil.class}) // 所有需要測試的類列在此處,適用于模擬final類或有final, private, static, native方法的類 @PowerMockIgnore("javax.management.*") //為了解決使用powermock后,提示classloader錯誤 public class MockExample {@Test   public void testStaticMethod() {     PowerMockito.mockStatic(MockUtil.class);     PowerMockito.when(MockUtil.nextInt(10)).thenReturn(7);     Assert.assertEquals(7, MockUtil.nextInt(10));   }}

Mock Final關(guān)鍵字

說明

(1)需要添加@RunWith(PowerMockRunner.class)注解和@PrepareForTest(ClassWithFinal.class)注解

(2)調(diào)用PowerMock.mock(ClassWithFinal.class)方法來mock final類的所有方法的,調(diào)用該方法將返回一個mock對象(暫且叫他mockObject)。

實例

final類StateHolder
提供一個getState方法返回一個調(diào)用其他接口的字符串

package com.cainiaoguoguo.mocktest.finalclass;public final class StateHolder {public String getState() {return innerMethod("MSG from StateHolder");}private String innerMethod(String msg) {return "INNER: " + msg;}}

需要測試的StateFormatter類
引用了StateHolder,要對StateFormatter類中的getFormattedState()方法進行測試

package com.cainiaoguoguo.mocktest.finalclass;public class StateFormatter {private final StateHolder stateHolder;public StateFormatter(StateHolder stateHolder) {this.stateHolder = stateHolder;}public String getFormattedState() {String safeState = "State information is missing";final String actualState = stateHolder.getState();if (actualState != null) {safeState = actualState;}return safeState;}}

測試類
目的要在調(diào)用getFormattedState()方法的過程中讓StateHolder的getState()方法返回符合預(yù)期的值

package com.cainiaoguoguo.mocktest.finalclass;import org.junit.Test;import org.junit.runner.RunWith;import org.powermock.core.classloader.annotations.PrepareForTest;import org.powermock.modules.junit4.PowerMockRunner;import static org.junit.Assert.assertEquals;import static org.powermock.api.mockito.PowerMockito.mock;import static org.powermock.api.mockito.PowerMockito.when;@RunWith(PowerMockRunner.class)@PrepareForTest(StateHolder.class)public class StateFormatterTest {@Testpublic void getFormattedState() throws Exception {final String expectedState = "state";StateHolder stateHolderMock = mock(StateHolder.class);when(stateHolderMock.getState()).thenReturn(expectedState);StateFormatter tested = new StateFormatter(stateHolderMock);String actualState = tested.getFormattedState();assertEquals(expectedState, actualState);}}

注意:
(1)需要添加@RunWith(PowerMockRunner.class)和@PrepareForTest(StateHolder.class)注解;

(2)調(diào)用PowerMockito.mock()方法mock需要被攔截的類;

(3)使用when…thenReturn…的模式返回期望得到的值。

局部Mock

說明

PowerMockito.spy():不mock一個類中的所有方法,而是mock部分方法

使用場景:當(dāng)要真實調(diào)用某些方法。

注意:
使用spy來錄制行為的時候使用when(…).thenXxx(…)的模式會直接調(diào)用原有方法,可能會和預(yù)期的結(jié)果不符合。正確的使用方式是doXXX(…).when(…).methodToMock(…)。

import org.junit.Test;import org.powermock.api.mockito.PowerMockito;import java.util.ArrayList;import java.util.List;public class SpyTest {@Testpublic void testSpy() {List list = new ArrayList();List spy = PowerMockito.spy(list);// 會拋出IndexOutOfBoundsException異常,因為會去調(diào)用spy.get(0)方法。PowerMockito.when(spy.get(0)).thenReturn("foo");// 正確的寫法如下PowerMockito.doReturn("foo").when(spy).get(0);}}

驗證行為

普通公有方法

驗證方式和靜態(tài)方法類似,調(diào)用Mockito.vertify()就可以進行標(biāo)準的行為驗證

@Testpublic void testSpy() {List list = new ArrayList();List spy = PowerMockito.spy(list);PowerMockito.doReturn("foo").when(spy).get(0);spy.get(0);spy.get(0);Mockito.verify(spy, Mockito.times(2)).get(0); //驗證spy.get(0)是否被調(diào)用兩次}

驗證私有方法

驗證私有方法使用PowerMockito.verifyPrivate()即可,該方法對靜態(tài)私有方法也適用

import org.junit.Test;import org.junit.runner.RunWith;import org.mockito.Mockito;import org.powermock.api.mockito.PowerMockito;import org.powermock.core.classloader.annotations.PrepareForTest;import org.powermock.modules.junit4.PowerMockRunner;@RunWith(PowerMockRunner.class)@PrepareForTest({PartialMockClass.class})public class SpyTest {@Testpublic void verifyPrivate() throws Exception {final String expectResult = "MESSAGE";String param = "param string";PartialMockClass classUnderTest = PowerMockito.spy(new PartialMockClass());PowerMockito.doReturn(expectResult).when(classUnderTest, "privateMethod", param);// 調(diào)用會執(zhí)行privateMethodassert(classUnderTest.publicMethod(param).equals(expectResult));// 使用PowerMockito.verify()驗證調(diào)用PowerMockito.verifyPrivate(classUnderTest, Mockito.times(1)).invoke("privateMethod", param);}}class PartialMockClass {public String publicMethod(String msg) {return privateMethod(msg);}private String privateMethod(String msg) {return "MSG:" + msg;}}

Mock構(gòu)造函數(shù)

說明

能模擬構(gòu)造函數(shù)從而使被測代碼中 new 操作返回的對象可以被隨意定制
會很大程度的提高單元測試的效率。

使用的形式是whenNew(MyClass.class).with[No|Any]Arguments().thenXXX(…)

示例

import org.junit.Test;import org.junit.runner.RunWith;import org.powermock.api.mockito.PowerMockito;import org.powermock.core.classloader.annotations.PrepareForTest;import org.powermock.modules.junit4.PowerMockRunner;import java.io.File;@RunWith(PowerMockRunner.class)@PrepareForTest({DirectoryStructure.class})public class ConstructionTest {@Testpublic void testConstruction() throws Exception {final String directoryPath = "mocked path";File directoryMock = PowerMockito.mock(File.class);// mock File的構(gòu)造函數(shù)PowerMockito.whenNew(File.class).withArguments(directoryPath).thenReturn(directoryMock);// 錄制行為PowerMockito.when(directoryMock.exists()).thenReturn(false);PowerMockito.when(directoryMock.mkdirs()).thenReturn(true);// 調(diào)用測試assert(new NewFileExample().createDirectoryStructure(directoryPath));// 驗證行為PowerMockito.verifyNew(File.class).withArguments(directoryPath);}}class NewFileExample {public boolean createDirectoryStructure(String path) {DirectoryStructure directoryStructure = new DirectoryStructure();return directoryStructure.create(path);}}class DirectoryStructure {public boolean create(String directoryPath) {File directory = new File(directoryPath);if (directory.exists()) {throw new IllegalArgumentException("\"" + directoryPath + "\" already exists.");}return directory.mkdirs();}}

總結(jié)

以上是生活随笔為你收集整理的PowerMock 入门的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。