gmock學習03---自定義輸出參數


本文目的

使用gmock時,有時候需要向被mock的函數輸入一些自定以參數,用來測試調用mock的方法的各種的執行情況。前幾天在項目中遇到這個問題,並使用了該技巧,覺得很有用,所以總結出來,作為備忘。

 

一個例子

XXXClient是一個類,用於和遠端服務器交互,內部實現涉及網絡通訊。

class XXXClient {
public:
    void QueryXXX(const Request&, Response&);
}; 

內部有個函數QueryXXX,用於執行查詢操作。查詢的響應對象通過引用的方式傳回給調用對象,避免不必要的對象拷貝。

現在有個類,會調用XXXClient::QueryXXX方法,如下面所示:

class XXXRunner {
public:
    QueryResult DoSomething(XXXClient& oClient)
    {
        Request oReq;
        … // 設置oReq

        Response oRsp;
        oClient.QueryXXX(oReq, oRsp);
    
        // 這里以后的邏輯需要測試
         … // 根據oRsp的內容,做一些相關邏輯,並創建QueryResult對象

         return oResult;
    }
};

現在希望做的是在測試用例中設置各種輸出(oRsp),測試調用QueryXXX之后的代碼邏輯,更重要的是,不希望為了執行單元測試,專門搭建一個服務器與XXXClient交互,成本太高

 

Gmock的解決方法

gmock內部實現了一系列Action的宏,可以幫我們完成上面的需求。先看看代碼,首先mock我們的XXXClient,

class XXXClientMock : public XXXClient
{
public:
    MOCK_METHOD2(QueryXXX, QueryResult (Request&, Response&));
};

Mock的XXXClient后,我們就可以使用mock對象在單元測試中測試了。

TEST(XXXRunnerTC, SetArgRefereeDemo)
{
    XXXCLientMock oMock;

    // 設計一個期望的oRsp返回對象
    Response oRsp;
    oRsp.attr1 = “…”; 
    oRsp.attr2 = “any thing you like”;

    // 關聯oRsp與mock對象的Query
    EXPECT_CALL(oMock,  QueryXXX(_, _)).
    WillOnce(SetArgReferee<1>(oRsp));
    // OK 設置完畢

    // 調用QueryXXX
    XXXRunner oRunner;
    QueryResult oRst = oRunner.DoSomething(oMock);
    …

    // 設置斷言
    EXPECT_EQ(“abcdefg”, oRst.attr1);
    ……
}

 

Gmock的Action

好了,現在解決了本文開始提出的問題,可以捎帶做一點擴展閱讀。上面用的一些API,在Gmock中稱之為Action(行為),主要目的是方便快速的為mock類提供測試行為,用於測試。上面,填充oRsp對象就是用SetArgReferee<N>(value)行為實現的,通過名字,可以知道這個行為對象是用於設置參數,N是參數的索引,從0開始。類似的行為還有SetArgPointee<N>(value),設置指針參數, SetArrayArgument<N>(first, last),設置數組參數,數組范圍[first,last)

設置返回值,可以使用行為Return(Value)等一些列API,更詳細的可以閱讀最后的“參考資料中的gmock cheat sheet”。

有時候,可能需要設置參數和返回值,也就是同時設置多個行為,那么可以使用DoAll函數幫我們實現,DoAll相當於一個action的集合,使用示例如下:

…
EXPECT_CALL(oMock,  QueryXXX(_, _)).
    WillOnce(DoAll(SetArgReferee<1>(oRsp), Return(someObj))));
…

還可以通過Invoke行為,將負責的測試行為添加進來。

 

總結

用了Gtest&Gmock框架一段時間了,發現使用之他們之后,的確可以提升代碼質量,並且加快bug定位,從某個側面來說,提高的編碼效率。現在,不論用什么語言寫程序,在熟悉了語言本身之后,第一件事就是去熟悉這門語言相關的單元測試框架。

個人認為寫單元測試不只是一種行為,更是一種信仰。

 

參考資料


免責聲明!

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



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