1 初識gmock
1.1 什么是Mock
便捷的模擬對象的方法。
1.2 Google Mock概述
google mock是用來配合google test對C++項目做單元測試的。它依賴於googletest
Google Mock(簡稱gmock)是Google在2008年推出的一套針對C++的Mock框架,它靈感取自於jMock、EasyMock、harcreat。它提供了以下這些特性:
- 輕松地創建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
官網,但我今天打不開官網了。