google mock是用來配合google test對C++項目做單元測試的。它依賴於googletest(參見我上篇文章《如何用googletest寫單元測試》:?http://blog.csdn.net/russell_tao/article/details/7333226),下面我來說說linux上怎么用它來做單元測試。
本文包括:1、如何獲取、編譯google mock;2、如何使用gmock(下面用gmock來代稱google mock)配合gtest做單元測試。
1、如何獲取、編譯google mock
gmock的當前版本與gtest一樣,是1.6.0。可以從這個網址獲取:http://code.google.com/p/googlemock/downloads/list。
下載到壓縮包解壓后,下面我們開始編譯出靜態庫文件(必須得自己編譯出),以在我們自己的單元測試工程中使用。
與gtest相同,我們執行完https://blog.csdn.net/russell_tao/article/details/configure; make后,不能執行make install,理由與上篇相同。
驗證這個包有沒有問題,依然可以執行如下命令:
如果你看到類似下文的輸出屏幕,證明你的機器運行gmock沒有問題。
這時還沒有編譯出我們要的libgmock.a呢。繼續在gmock解包目錄下執行:
如此,當前目錄下會鏈接出我們需要的libgmock.a。注意,這個gmock.a靜態庫里,把gtest需要的gtest-all.cc都編譯進來了,所以我們的單元測試工程只需要鏈接libgmock,不再需要鏈接上文說的libgtest了。
2、如何使用gmock
首先,編譯我們自己的單元測試工程時,需要在makefile里加入以下編譯選項:-I${GTEST_DIR}/include -I${GMOCK_DIR}/include,這兩個目錄我們自己從上面的包里拷貝出來即可。鏈接時,需要加上libgmock.a。
還是以一個例子來說明怎么在mock對象的情況下寫單元測試。
我現在有一個生產者消費者網絡模型,消費者(例如client)會先發TCP請求到我的SERVER去訂閱某個對象。生產者(另一台SERVER)產生關於某個對象的事件后發給我的SERVER后,我的SERVER再把事件發給消費者。
就是這么簡單。
我現在想寫一個單元測試,主要測試代碼邏輯,不想去管網絡包的收發這些事情。
我現在有兩個類,一個叫CSubscriber,它封裝為一個訂閱的消費者,功能主要是操作網絡,包括網絡收發包,協議解析等。另一個叫CSubEventHandler,它主要做邏輯處理,去操作CSubscriber對象,例如epoll返回讀事件后,會構造一個CSubscriber對象,然后CSubEventHandler::handleRead方法就來處理這個CSubscriber對象。
我單元測試的目的是,測試CSubEventHandler::handleRead的業務邏輯,我同時也想測試CSubscriber方法里的協議解析邏輯,但是對於CSubscriber封裝的讀寫包部分,我希望可以mock成我想要的網絡包。
怎么做呢?
a)、先mock一個CSubscriber類如下:
其中,CSubscriber的構造方法必須有一個int型的fd,而readBuf和writeBuf都只接收一個int型的參數,而closeSock方法 沒有參數傳遞。於是我使用了MOCK_METHOD0和MOCK_METHOD1這兩個宏來聲明想MOCK的方法。這兩個宏的使用很簡單,解釋下:
MOCK_METHOD#1(#2, #3(#4) )
#2是你要mock的方法名稱!#1表示你要mock的方法共有幾個參數,#4是這個方法具體的參數,#3表示這個方法的返回值類型。
很簡單不是?!
b)、如果只關心mock方法的返回值。
這里用到一個宏ON_CALL。看例子:
什么意思呢?再用剛才的解釋方法:
ON_CALL(#1, #2(#3)).WillByDefault(Return(#4));
#1表示mock對象。就像我上面所說,對CSubscriber我定義了一個Mock類,那么就必須生成相應的mock對象,例如:
#2表示想定義的那個方法名稱。上例中我想定義readBuf這個方法的返回值。
#3表示readBuf方法的參數。這里的1000表示,只有調用CSubscriber::readBuf同時傳遞參數為1000時,才會用到ON_CALL的定義。
#4表示調用CSubscriber::readBuf同時傳遞參數為1000時,雅思怎么讀返回blen這個變量的值。
c)、如果還希望mock方法有固定的被調用方式
這里用到宏EXPECT_CALL,看個例子:
很相似吧?最后的Times表示,只希望readBuf在傳遞參數為1000時,被調用且僅被調用一次。
其實這些宏有很復雜的用法的,例如:
表示,readBuf希望被調用五次,第一次返回100,第二次返回150,后三次返回200。如果不滿足,會報錯。
d)、實際的調用測試
其實調用跟上篇googletest文章里的測試是一致的,我這里只列下上文的完整用例代碼(不包括被測試類的實現代碼):
CSubscriber的頭文件:
e)、main函數的寫法
與gtest相同,唯一的區別是初始化參數,如下:
如此,就可以完整的使用googletest/googlemock做C++工程的單元測試了,確實很簡單好用。