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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Google Mock(Gmock)简单使用和源码分析——简单使用

發(fā)布時間:2023/11/27 生活经验 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Google Mock(Gmock)简单使用和源码分析——简单使用 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

? ? ? ? 初識Gmock是之前分析GTest源碼時,它的源碼和GTest源碼在同一個代碼倉庫中(https://github.com/google/googletest)。本文我將以目前最新的Gmock1.7版本為范例,分析其實現(xiàn)原理。(轉(zhuǎn)載請指明出于breaksoftware的csdn博客)

? ? ? ? Gmock是google開發(fā)的一套輔助測試的工具,它往往和GTest結(jié)合在一起使用。在實際工作中,一個人不可能完成整條線的開發(fā)工作。于是我們會在約定接口的前提下,各自完成各自的模塊。自己的模塊開發(fā)完之后,我們需要自測。但是這個時候別人的模塊可能還沒完成,那么我們就需要模擬約定的接口進行自測。Gmock就是一個強大的模擬接口的工具。

使用方法

? ? ? ? 首先我們講解一下其主要的使用方法。目前網(wǎng)絡(luò)上有一篇寫的不錯的使用說明《轉(zhuǎn)一篇小亮同學的google mock分享》,如果大家想了解其詳細的使用方法,可以參閱這篇文章。如果只是想簡單的了解其使用并理解其實現(xiàn)原理,可以先參閱本文。

? ? ? ? 我們假設(shè)一個支付場景邏輯開發(fā)業(yè)務(wù)。我們開發(fā)復雜的業(yè)務(wù)模塊,而團隊其他成員開發(fā)用戶行為模塊。他們和我們約定了如下接口

class User {
public:User() {};~User() {};
public:// 登錄virtual bool Login(const std::string& username, const std::string& password) = 0;// 支付virtual bool Pay(int money) = 0;// 是否登錄virtual bool Online() = 0;
};

? ? ? ? 我們的業(yè)務(wù)模塊要讓用戶登錄,并發(fā)起支付行為。于是我們的代碼如下

class Biz {
public:void SetUser(User* user) {_user = user;}std::string pay(const std::string& username, const std::string& password, int money) {std::string ret;if (!_user) {ret = "pointer is null.";return ret;}if (!_user->Online()) {ret = "logout status.";// 尚未登錄,要求登錄if (!_user->Login(username, password)) {// 登錄失敗ret += "login error.";return ret;} else {// 登錄成功ret += "login success.";}} else {// 已登錄ret = "login.status";}if (!_user->Pay(money)) {ret += "pay error.";} else {ret += "pay success.";}return ret;}private:User* _user;
};

? ? ? ? 這段邏輯的口語描述就是:我們先看看用戶登錄了沒,如果沒有登錄則要求用戶登錄。如果登錄失敗,則直接返回;如果登錄成功,則執(zhí)行支付行為。最后將流程的狀態(tài)輸出。

? ? ? ? 那我們?nèi)绾问褂肎mock輔助測試呢?

?? ? ? ?第一步我們需要Mock接口類

class TestUser : public User {
public:MOCK_METHOD2(Login, bool(const std::string&, const std::string&));MOCK_METHOD1(Pay, bool(int));MOCK_METHOD0(Online, bool());
};

? ? ? ? 可以發(fā)現(xiàn)其方法的聲明非常有規(guī)律。MOCK_METHOD后跟一個數(shù)字,該數(shù)字表明需要mock的函數(shù)有幾個參數(shù)(除去this)。像第5行,Online()方法沒有入?yún)?#xff0c;則使用的是MOCK_METHOD0。而又兩個參數(shù)的Login使用的是MOCK_METHOD2。MOCK_METHOD系列宏的第一個參數(shù)是函數(shù)名,第二個參數(shù)是函數(shù)指針的類型。

? ? ? ? 第二步,我們就可以設(shè)計測試場景了。在設(shè)計場景之前,我們先看一些Gmock的方法

//   EXPECT_CALL(mock_object, Method(argument-matchers))
//       .With(multi-argument-matchers)
//       .Times(cardinality)
//       .InSequence(sequences)
//       .After(expectations)
//       .WillOnce(action)
//       .WillRepeatedly(action)
//       .RetiresOnSaturation();
//
// where all clauses are optional, and .InSequence()/.After()/
// .WillOnce() can appear any number of times.

? ? ? ? 我們可以使用

  • EXPECT_CALL聲明一個調(diào)用期待,就是我們期待這個對象的這個方法按什么樣的邏輯去執(zhí)行。
  • mock_object是我們mock的對象,上例中就是TestUser的一個對象。
  • Method是mock對象中的mock方法,它的參數(shù)可以通過argument-matchers規(guī)則去匹配。
  • With是多個參數(shù)的匹配方式指定。
  • Times表示這個方法可以被執(zhí)行多少次。如果超過這個次數(shù),則按默認值返回了。
  • InSequence用于指定函數(shù)執(zhí)行的順序。它是通過同一序列中聲明期待的順序確定的。
  • After方法用于指定某個方法只能在另一個方法之后執(zhí)行。
  • WillOnce表示執(zhí)行一次方法時,將執(zhí)行其參數(shù)action的方法。一般我們使用Return方法,用于指定一次調(diào)用的輸出。
  • WillRepeatedly表示一直調(diào)用一個方法時,將執(zhí)行其參數(shù)action的方法。需要注意下它和WillOnce的區(qū)別,WillOnce是一次,WillRepeatedly是一直。
  • RetiresOnSaturation用于保證期待調(diào)用不會被相同的函數(shù)的期待所覆蓋。

? ? ? ? 我們就可以基于以上的邏輯組織測試邏輯。

? ? ? ? 先舉一個例子,我們要求Online在第一調(diào)用時返回true,之后都返回false。Login一直返回false。Pay一直返回true。也就是說用戶第一次支付前處于在線狀態(tài),并可以支付成功。而第二次將因為不處于在線狀態(tài),要觸發(fā)登錄行為,而登錄行為將失敗。我們看下這個邏輯該怎么寫

    {TestUser test_user;EXPECT_CALL(test_user, Online()).WillOnce(testing::Return(true));EXPECT_CALL(test_user, Login(_,_)).WillRepeatedly(testing::Return(false));EXPECT_CALL(test_user, Pay(_)).WillRepeatedly(testing::Return(true));Biz biz;biz.SetUser(&test_user);std::string admin_ret = biz.pay("user", "", 1);admin_ret = biz.pay("user", "", 1);}

? ? ? ? 第4行的意思是Online在調(diào)用一次后返回true,之后的調(diào)用返回默認的false。第5行意思是Login操作一直返回false,其中Login的參數(shù)是兩個下劃線(_),它是通配符,就是對任何輸入?yún)?shù)都按之后要求執(zhí)行。第6行意思是Pay操作總是返回true。那么我們在第10行和第11行分別得到如下輸出

login status.pay success.
logout status.login error.

? ? ? ? 可以見得輸出符合我們的預期。

? ? ? ? 我們再看一種場景,這個場景我們使用了函數(shù)參數(shù)的過濾。比如我們不允許admin的用戶通過我們方法登錄并支付,則可以這么寫

    {TestUser test_user;EXPECT_CALL(test_user, Online()).WillOnce(testing::Return(false));EXPECT_CALL(test_user, Login("admin",_)).WillRepeatedly(testing::Return(false));Biz biz;biz.SetUser(&test_user);std::string admin_ret = biz.pay("admin", "", 1);}

? ? ? ? 第3行表示,如果Login的第一個參數(shù)是admin,則總是返回false。于是07行返回是

logout status.login error.

? ? ? ? 那么如果不是admin的用戶登錄,則返回成功,這個案例要怎么寫呢?

    {TestUser test_user;EXPECT_CALL(test_user, Online()).WillOnce(testing::Return(false));EXPECT_CALL(test_user, Login(StrNe("admin"),_)).WillRepeatedly(testing::Return(true));EXPECT_CALL(test_user, Pay(_)).WillRepeatedly(testing::Return(true));Biz biz;biz.SetUser(&test_user);std::string user_ret = biz.pay("user", "", 1);}

? ? ? ? 03行使用了StrNe的比較函數(shù),即Login的第一個參數(shù)不等于admin時,總是返回true。08行的輸出是

logout status.login success.pay success.

? ? ? ? 我們再看一個例子,我們要求非admin用戶登錄成功后,只能成功支付2次,之后的支付都失敗。這個案例可以這么寫

    {TestUser test_user;EXPECT_CALL(test_user, Online()).WillOnce(testing::Return(false));EXPECT_CALL(test_user, Login(StrNe("admin"),_)).WillRepeatedly(testing::Return(true));EXPECT_CALL(test_user, Pay(_)).Times(5).WillOnce(testing::Return(true)).WillOnce(testing::Return(true)).WillRepeatedly(testing::Return(false));Biz biz;biz.SetUser(&test_user);std::string user_ret = biz.pay("user", "", 1);user_ret = biz.pay("user", "", 1);user_ret = biz.pay("user", "", 1);}

? ? ? ? 第4行我們使用Times函數(shù),它的參數(shù)5表示該函數(shù)期待被調(diào)用5次,從第6次的調(diào)用開始,返回默認值。Times函數(shù)后面跟著兩個WillOnce,其行為都是返回true。這個可以解讀為第一次和第二次調(diào)用Pay方法時,返回成功。最后的WillRepeatedly表示之后的對Pay的調(diào)用都返回false。我們看下執(zhí)行的結(jié)果

logout status.login success.pay success.
logout status.login success.pay success.
logout status.login success.pay error.

? ? ? ? 從結(jié)果上看,前兩次都支付成功了,而第三次失敗。符合我們的期待。

? ? ? ? 下一節(jié),我們將閱讀Gmock的源碼,分析其實現(xiàn)脈絡(luò)和原理。

總結(jié)

以上是生活随笔為你收集整理的Google Mock(Gmock)简单使用和源码分析——简单使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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