gmock使用、原理及源碼分析


1      初識gmock

1.1      什么是Mock

便捷的模擬對象的方法。

1.2      Google Mock概述

google mock是用來配合google test對C++項目做單元測試的。它依賴於googletest

Google Mock(簡稱gmock)是Google在2008年推出的一套針對C++的Mock框架,它靈感取自於jMockEasyMockharcreat。它提供了以下這些特性:

  • 輕松地創建mock類
  • 支持豐富的匹配器(Matcher)和行為(Action)
  • 支持有序、無序、部分有序的期望行為的定義
  • 多平台的支持

1.3      獲取、編譯google mock

見gtest,gtest項目里就包含gmock

 

1.4      最簡單的例子

class MockFoo: public FooInterface {
public:
        MOCK_METHOD0(getArbitraryString, std::string());
};

using ::testing::Return;

int main(int argc, char** argv) {
        ::testing::InitGoogleMock(&argc, argv);

        string value = "Hello World!";
        MockFoo mockFoo;
        EXPECT_CALL(mockFoo, getArbitraryString()).Times(1).
                WillOnce(Return(value));
        string returnValue = mockFoo.getArbitraryString();
        cout << "Returned Value: " << returnValue << endl;

        return EXIT_SUCCESS;
}

 

 

2      典型的流程

通過上述的例子,已經可以看出使用Mock類的一般流程如下:

  • 引入你要用到的Google Mock名稱. 除宏或其它特別提到的之外所有Google Mock名稱都位於*testing*命名空間之下.
  • 建立模擬對象(Mock Objects).
  • 可選的,設置模擬對象的默認動作.
  • 在模擬對象上設置你的預期(它們怎樣被調用,應該怎樣回應?).

 

2.1      自定義方法/成員函數的期望行為

在單元測試/主程序中使用這個Mock類中的方法時最關鍵的就是對期望行為的定義。

對方法期望行為的定義的語法格式如下:

EXPECT_CALL(mock_object, method(matcher1, matcher2, ...))
    .With(multi_argument_matcher)
    .Times(cardinality)
    .InSequence(sequences)
    .After(expectations)
    .WillOnce(action)
    .WillRepeatedly(action)
    .RetiresOnSaturation();

 

解釋一下這些參數(雖然很多我也沒弄明白):

  • 第1行的mock_object就是你的Mock類的對象
  • 第1行的method(matcher1, matcher2, …)中的method就是你Mock類中的某個方法名,比如上述的getArbitraryString;而matcher(匹配器)的意思是定義方法參數的類型,我們待會詳細介紹。
  • 第3行的Times(cardinality)的意思是之前定義的method運行幾次。至於cardinality的定義,我也會在后面詳細介紹。
  • 第4行的InSequence(sequences)的意思是定義這個方法被執行順序(優先級),我會再后面舉例說明。
  • 第6行WillOnce(action)是定義一次調用時所產生的行為,比如定義該方法返回怎么樣的值等等。
  • 第7行WillRepeatedly(action)的意思是缺省/重復行為。

 

先舉個例子來說明一下,后面有針對更為詳細的說明:

EXPECT_CALL(mockTurtle, getX()).Times(testing::AtLeast(5)).
                WillOnce(testing::Return(100)).WillOnce(testing::Return(150)).
                WillRepeatedly(testing::Return(200))

 

這個期望行為的定義的意思是:

  • 調用mockTurtle的getX()方法
  • 這個方法會至少調用5次
  • 第一次被調用時返回100
  • 第2次被調用時返回150
  • 從第3次被調用開始每次都返回200

 

2.2      Matcher(匹配器)

Matcher用於定義Mock類中的方法的形參的值(當然,如果你的方法不需要形參時,可以保持match為空。),就是判斷在調用這個函數時,入參的值是否符合預先設置的條件,就是一個預設的EXPECT_TRUE。

它有以下幾種類型:

一般比較、浮點數的比較、字符串匹配、容器的匹配、成員匹配器、匹配函數或函數對象的返回值、指針匹配器、復合匹配器

具體參考原文吧https://www.cnblogs.com/welkinwalker/archive/2011/11/29/2267225.html

2.3      基數(Cardinalities)

基數用於Times()中來指定模擬函數將被調用多少次|

2.4      行為(Actions)

Actions(行為)用於指定Mock類的方法所期望模擬的行為:比如返回什么樣的值、對引用、指針賦上怎么樣個值,等等。 值的返回

Return()

讓Mock方法返回一個void結果

Return(value)

返回值value

ReturnNull()

返回一個NULL指針

ReturnRef(variable)

返回variable的引用.

ReturnPointee(ptr)

返回一個指向ptr的指針

另一面的作用(Side Effects

Assign(&variable, value)

將value分配給variable

使用函數或者函數對象(Functor)作為行為

Invoke(f)

使用模擬函數的參數調用f, 這里的f可以是全局/靜態函數或函數對象.

Invoke(object_pointer, &class::method)

使用模擬函數的參數調用object_pointer對象的mothod方法.

復合動作

DoAll(a1, a2, …, an)

每次發動時執行a1到an的所有動作.

IgnoreResult(a)

執行動作a並忽略它的返回值. a不能返回void.

 

復合行為舉例:

    EXPECT_CALL(mockIParameter, getParamter(testing::_, testing::_)).Times(1).\
        WillOnce(testing::DoAll(testing::Assign(&a, b), testing::Return(1)));

 

2.5      序列(Sequences)

默認時,對於定義要的期望行為是無序(Unordered)的,但有時候我們需要定義有序的(Ordered)的調用方式,即序列 (Sequences) 指定預期的順序. 在同一序列里的所有預期調用必須按它們指定的順序發生; 反之則可以是任意順序.

 

3      Google Mock Cookbook

3.1      Mock protected、private方法

Google Mock也可以模擬protected和private方法,比較神奇啊(其實從這點上也可以看出,Mock類不是簡單地繼承原本的接口,然后自己把它提供的方法實現;Mock類其實就等於原本的接口)。

對protected和private方法的Mock和public基本類似,只不過在Mock類中需要將這些方法設置成public。

3.2      Mock 模版類(Template Class)

Google Mock可以Mock模版類,只要在宏MOCK*的后面加上T。

 

4      Gmock原理及源碼分析

4.1      基本原理

EXPECT_CALL.WillOnce的核心工作: untyped_actions_.push_back(new Action<F>(action)); 也就是說它將返回值塞進了一個vector容器中。

MOCK_METHOD0的核心工作:this->UntypedInvokeWith(&args))->GetValueAndDelete();也就是說它從之前說的那個vector中取出返回的結果被刪除。

參見:單元測試Mock之c++ gmock實現原理 https://www.jianshu.com/p/06f0a7d85877

 

4.2      源碼分析

參見:Google Mock(Gmock)簡單使用和源碼分析——源碼分析 https://blog.csdn.net/breaksoftware/article/details/51438033

 

5      參考文檔

轉一篇小亮同學的google mock分享https://www.cnblogs.com/welkinwalker/archive/2011/11/29/2267225.html

單元測試Mock之c++ gmock實現原理 https://www.jianshu.com/p/06f0a7d85877

Google Mock(Gmock)簡單使用和源碼分析——源碼分析 https://blog.csdn.net/breaksoftware/article/details/51438033

官網,但我今天打不開官網了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM