欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java單元測(cè)試Powermockito和Mockito使用總結(jié)

 更新時(shí)間:2021年09月08日 11:54:48   作者:LJWLgl  
公司單元測(cè)試框架選用了Junit 4.12,Mock框架選用了Mockito和PowerMock,本文主要介紹了Java單元測(cè)試Powermockito和Mockito使用總結(jié),感興趣的可以了解一下

最近公司在推進(jìn)Java應(yīng)用的單元測(cè)試,要求將單元測(cè)試的覆蓋率提高到50%以上,保證上線代碼充分自測(cè)。公司單元測(cè)試框架選用了Junit 4.12,Mock框架選用了Mockito和PowerMock,同時(shí)選用JaCoCo來做覆蓋率檢測(cè),下面詳細(xì)介紹一下我在使用這幾個(gè)框架的一些經(jīng)驗(yàn)。

依賴引入

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>2.8.9</version>
    <scope>test</scope>
</dependency>
<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>

PowerMockito的使用

Mockito、EasyMock、JMock等比較流行Mock框架有個(gè)共同的缺點(diǎn),都不能mock靜態(tài)、final、私有方法等,而PowerMock可以完美解決以上框架的不足,接下來讓我們看看無所不能的PowerMock是如何解決上述問題,我們先從一個(gè)實(shí)例來看,下面的代碼是需要單測(cè)的類,被測(cè)類中既有對(duì)Spring Bean的調(diào)用,同時(shí)又包含對(duì)Redis的靜態(tài)讀取,另外還有g(shù)etInstance()單例類的使用,現(xiàn)在,我們一一來mock上述的外部類。

被單測(cè)類(主要測(cè)試queryStudentScoreByKeyword方法)

@Component
public class StudentService {

    @Resource
    private StudentDao studentDao;

    public List<StudentBo> queryStudentScoreByKeyword(String name) {
        System.out.println("invoke StudentService.queryStudentScoreByKeyword ...");

        List<StudentBo> cacheList = RedisUtils.getArray(name, StudentBo.class);
        if (CollectionUtils.isNotEmpty(cacheList)) {
            return cacheList;
        }
        String keyword = processKeyword(name);
        List<Student> students = studentDao.queryStudentByKeyWord(keyword);
        List<Integer> ids = students.stream().map(Student::getId).collect(Collectors.toList());
        List<Person> personList = SchoolManageProxy.getInstance().queryPerson(ids);

        List<StudentBo> studentBos = CommonUtils.toBo(personList, students);
        // 高亮結(jié)果
        highlightResult(studentBos, name);
        // 緩存到Redis
        RedisUtils.setArray(name, studentBos, 10 * 60);
        return studentBos;
    }

    private String processKeyword(String name) {
        System.out.println("invoke StudentService.processKeyword ...");
        String newName = name;
        // do somethings
        return newName;
    }

    private void highlightResult(List<StudentBo> result, String name) {
        System.out.println("invoke StudentService.highlightResult ...");
        // do keyword highlight
    }

}

單測(cè)類

@RunWith(PowerMockRunner.class)
@PrepareForTest({SchoolManageProxy.class, RedisUtils.class, StudentService.class})
// @PowerMockIgnore({"javax.management.*", "javax.net.ssl.*"})
@SuppressStaticInitializationFor({"cn.ganzhiqiang.ares.unittest.SchoolManageProxy"})
public class StudentServiceTest {

    @Mock
    private StudentDao mockStudentDao;

    @InjectMocks
    private StudentService studentServiceUnderTest;

    @Before
    public void setUp() {
        initMocks(this);
    }

    @Test
    public void testQueryStudentScoreByKeyword() throws Exception {
        studentServiceUnderTest = PowerMockito.spy(studentServiceUnderTest);
        PowerMockito.mockStatic(RedisUtils.class);
        PowerMockito.mockStatic(SchoolManageProxy.class);

        // mock單例調(diào)用
        SchoolManageProxy mockSchoolManageProxy = PowerMockito.mock(SchoolManageProxy.class);
        PowerMockito.when(SchoolManageProxy.getInstance()).thenReturn(mockSchoolManageProxy);
        when(mockSchoolManageProxy.queryPerson(anyList())).thenReturn(Collections.emptyList());

        // mock掉對(duì)Redis的靜態(tài)調(diào)用
        PowerMockito.when(RedisUtils.getArray(eq("tom"), eq(StudentBo.class))).thenReturn(Collections.emptyList());
        // 顯示的mock掉靜態(tài)的void的方法(可以不mock)
        PowerMockito.doNothing().when(RedisUtils.class, "setArray", anyString(), anyList(), anyInt());

        // mock私有方法processKeyword
        PowerMockito.doReturn("tom").when(studentServiceUnderTest, "processKeyword", anyString());

        // 跳過私有方法highlightResult的執(zhí)行
        PowerMockito.suppress(PowerMockito.method(StudentService.class, "highlightResult"));

        // 使用Mockito來mock服務(wù)的調(diào)用
        when(mockStudentDao.queryStudentByKeyWord(anyString())).thenReturn(Collections.emptyList());

        // Run the test
        final List<StudentBo> result = studentServiceUnderTest.queryStudentScoreByKeyword("tom");

    }
}

使用mockito來mock實(shí)例

首選我們先用Mockito來mock對(duì)Spring Bean的調(diào)用,Mockito.mock可以mock一個(gè)實(shí)例,我們這里選用@Mock注解,效果是一樣的。

// 使用Mockito來mock服務(wù)的調(diào)用 
when(mockStudentDao.queryStudentByKeyWord(anyString())).thenReturn(Collections.emptyList());

mock對(duì)Redis的靜態(tài)調(diào)用

接下來我們使用PowerMock來mock對(duì)靜態(tài)方法的調(diào)用,注意需要將RedisUtils類,加入@PrepareForTest注解中,我們既mock了getArray方法,也mock了setArray方法,其實(shí)setArray不需要mock這里顯式的mock了

PowerMockito.mockStatic(RedisUtils.class);
// mock掉對(duì)Redis的靜態(tài)調(diào)用
PowerMockito.when(RedisUtils.getArray(eq("tom"), eq(StudentBo.class))).thenReturn(Collections.emptyList());
// 顯式的mock掉靜態(tài)的void的方法(可以不mock)
PowerMockito.doNothing().when(RedisUtils.class, "setArray", anyString(), anyList(), anyInt());

mock單例類

mock單例類相對(duì)來說復(fù)雜一點(diǎn),邏輯上先用Powermock mock出單例類,然后再給單例類的getInstance方法打樁,返回之前mock,再對(duì)mock類實(shí)際調(diào)用的方法打樁即可,代碼如下

PowerMockito.mockStatic(SchoolManageProxy.class);
// Powermock mock出單例類
SchoolManageProxy mockSchoolManageProxy = PowerMockito.mock(SchoolManageProxy.class);
// 給單例類的getInstance方法打樁

PowerMockito.when(SchoolManageProxy.getInstance()).thenReturn(mockSchoolManageProxy);
// 對(duì)mock類queryPerson的方法打樁
when(mockSchoolManageProxy.queryPerson(anyList())).thenReturn(Collections.emptyList());

mock私有方法

可以看到queryStudentScoreByKeyword方法調(diào)用了該類的私有方法processKeyword,如果該方法耗時(shí)過長,使用powermock也可以mock該私有方法,需要注意的studentServiceUnderTest需要用spy()來mock

// mock 實(shí)例
// spy的標(biāo)準(zhǔn)是:如果不打樁,默認(rèn)執(zhí)行真實(shí)的方法,如果打樁則返回樁實(shí)現(xiàn)。
studentServiceUnderTest = PowerMockito.spy(studentServiceUnderTest);
// mock私有方法processKeyword
// doReturn(...) when(...)不做真實(shí)調(diào)用,但是when(...) thenReturn(...)還是會(huì)真實(shí)調(diào)用原方法,只是返回了指定的結(jié)果
PowerMockito.doReturn("tom").when(studentServiceUnderTest, "processKeyword", anyString());

PowerMock跳過方法執(zhí)行

使用PowerMock也可以跳過私有方法的執(zhí)行

// 跳過私有方法highlightResult的執(zhí)行
PowerMockito.suppress(PowerMockito.method(StudentService.class, "highlightResult"));

總結(jié)

筆者之前寫代碼很少會(huì)寫單測(cè),自從公司強(qiáng)制要求提高單測(cè)覆蓋率之后,雖然開發(fā)效率變慢了,但是確實(shí)引起我對(duì)單測(cè)的重視,進(jìn)而研究了一下PowerMockito、Mokcito等Mock框架。Powermock之所以無所不能,是因?yàn)樗褂昧俗远x的加載器和字節(jié)碼操作技術(shù),與此同時(shí),它還十分簡單易用,確實(shí)是個(gè)很優(yōu)秀的框架。

Demo地址:https://github.com/LJWLgl/mock-data

參考文檔

PowerMock
powermockito單元測(cè)試之深入實(shí)踐
淺談測(cè)試之PowerMock
無所不能的PowerMock,mock私有方法,靜態(tài)方法,測(cè)試私有方法,final類
Mock和Spy的區(qū)別

到此這篇關(guān)于Java單元測(cè)試Powermockito和Mockito使用總結(jié)的文章就介紹到這了,更多相關(guān)Java Powermockito和Mockito 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java優(yōu)雅的處理金錢問題(BigDecimal)

    Java優(yōu)雅的處理金錢問題(BigDecimal)

    本文主要介紹了Java優(yōu)雅的處理金錢問題(BigDecimal),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • Java8新特性之JavaFX 8_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java8新特性之JavaFX 8_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了Java8新特性之JavaFX 8的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧
    2017-06-06
  • JAVA mongodb 聚合幾種查詢方式詳解

    JAVA mongodb 聚合幾種查詢方式詳解

    這篇文章主要介紹了JAVA mongodb 聚合幾種查詢方式詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-03-03
  • JavaWeb實(shí)現(xiàn)文件上傳下載功能實(shí)例解析

    JavaWeb實(shí)現(xiàn)文件上傳下載功能實(shí)例解析

    這篇文章主要為大家詳細(xì)介紹了JavaWeb中的文件上傳和下載功能的實(shí)現(xiàn),在Web應(yīng)用系統(tǒng)開發(fā)中,文件上傳和下載功能是非常常用的功能,需要的朋友可以參考下
    2015-08-08
  • Java中常用解析工具jackson及fastjson的使用

    Java中常用解析工具jackson及fastjson的使用

    今天給大家?guī)淼氖顷P(guān)于Java解析工具的相關(guān)知識(shí),文章圍繞著jackson及fastjson的使用展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • java動(dòng)態(tài)規(guī)劃算法——硬幣找零問題實(shí)例分析

    java動(dòng)態(tài)規(guī)劃算法——硬幣找零問題實(shí)例分析

    這篇文章主要介紹了java動(dòng)態(tài)規(guī)劃算法——硬幣找零問題,結(jié)合實(shí)例形式分析了java動(dòng)態(tài)規(guī)劃算法——硬幣找零問題相關(guān)原理、實(shí)現(xiàn)方法與操作注意事項(xiàng),需要的朋友可以參考下
    2020-05-05
  • intelij?idea?2023創(chuàng)建java?web項(xiàng)目的完整步驟

    intelij?idea?2023創(chuàng)建java?web項(xiàng)目的完整步驟

    這篇文章主要給大家介紹了關(guān)于intelij?idea?2023創(chuàng)建java?web項(xiàng)目的完整步驟,該教學(xué)主要針對(duì)各位剛剛接觸javaweb開發(fā)的小伙伴,各位學(xué)習(xí)java的朋友也難免會(huì)經(jīng)歷這個(gè)階段,需要的朋友可以參考下
    2023-10-10
  • 詳解Java JDK動(dòng)態(tài)代理

    詳解Java JDK動(dòng)態(tài)代理

    這篇文章主要介紹了Java JDK動(dòng)態(tài)代理的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java 代理的有關(guān)知識(shí),感興趣的朋友可以了解下
    2020-08-08
  • Java縮小文件內(nèi)存占用的方法技巧分享

    Java縮小文件內(nèi)存占用的方法技巧分享

    在Java應(yīng)用程序中,處理大文件時(shí)經(jīng)常會(huì)遇到內(nèi)存占用過高的問題,為了縮小文件的內(nèi)存占用,我們可以采取一些有效的方法來優(yōu)化和管理內(nèi)存的使用,本文將介紹一些在Java中縮小文件內(nèi)存占用的技巧,需要的朋友可以參考下
    2024-10-10
  • SpringCloud中的Stream服務(wù)間消息傳遞詳解

    SpringCloud中的Stream服務(wù)間消息傳遞詳解

    這篇文章主要介紹了SpringCloud中的Stream服務(wù)間消息傳遞詳解,Stream 就是在消息隊(duì)列的基礎(chǔ)上,對(duì)其進(jìn)行封裝,可以是我們更方便的去使用,Stream應(yīng)用由第三方的中間件組成,應(yīng)用間的通信通過輸入通道和輸出通道完成,需要的朋友可以參考下
    2024-01-01

最新評(píng)論