用google mock模擬C 物件

2021-08-26 18:59:16 字數 4217 閱讀 1765

google mock是用來配合google test對c++專案做單元測試的。它依賴於googletest(參見我上篇文章《如何用googletest寫單元測試》:下面我來說說linux上怎麼用它來做單元測試。

1、如何獲取、編譯google mock

gmock的當前版本與gtest一樣,是1.6.0。可以從這個**獲取:

與gtest相同,我們執行完./configure; make後,不能執行make install,理由與上篇相同。

驗證這個包有沒有問題,依然可以執行如下命令:

cd make

make

./gmock_test

如果你看到類似下文的輸出螢幕,證明你的機器執行gmock沒有問題。

[----------] global test environment tear-down

[**********] 13 tests from 3 test cases ran. (2 ms total)

[ passed ] 13 tests.

這時還沒有編譯出我們要的libgmock.a呢。繼續在gmock解包目錄下執行:

g++ -i gtest/include/ -i gtest/ -i include/ -i ./ -c gtest/src/gtest-all.cc 

g++ -i gtest/include/ -i gtest/ -i include/ -i ./ -c src/gmock-all.cc

ar -rv libgmock.a gtest-all.o gmock-all.o

如此,當前目錄下會鏈結出我們需要的libgmock.a。注意,這個gmock.a靜態庫里,把gtest需要的gtest-all.cc都編譯進來了,所以我們的單元測試工程只需要鏈結libgmock,不再需要鏈結上文說的libgtest了。

2、如何使用gmock

首先,編譯我們自己的單元測試工程時,需要在makefile裡加入以下編譯選項:-i$/include -i$/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類如下:

class mockcsubscriber : public csubscriber

mock_method1(readbuf, int(int len));

mock_method1(writebuf, int(int len));

mock_method0(closesock, void());

};

其中,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(subobj, readbuf(1000)).willbydefault(return(blen));

什麼意思呢?再用剛才的解釋方法:

on_call(#1, #2(#3)).willbydefault(return(#4));

#1表示mock物件。就像我上面所說,對csubscriber我定義了乙個mock類,那麼就必須生成相應的mock物件,例如:

mockcsubscriber subobj(5);

#2表示想定義的那個方法名稱。上例中我想定義readbuf這個方法的返回值。

#3表示readbuf方法的引數。這裡的1000表示,只有呼叫csubscriber::readbuf同時傳遞引數為1000時,才會用到on_call的定義。

#4表示呼叫csubscriber::readbuf同時傳遞引數為1000時,返回blen這個變數的值。

c)、如果還希望mock方法有固定的被呼叫方式

這裡用到巨集expect_call,看個例子:

expect_call(subobj, readbuf(1000)).times(1);

很相似吧?最後的times表示,只希望readbuf在傳遞引數為1000時,被呼叫且僅被呼叫一次。

其實這些巨集有很複雜的用法的,例如:

expect_call(subobj, readbuf(1000))

.times(5)

.willonce(return(100))

.willonce(return(150))

.willrepeatedly(return(200));

表示,readbuf希望被呼叫五次,第一次返回100,第二次返回150,後三次返回200。如果不滿足,會報錯。

d)、實際的呼叫測試

#include "gtest/gtest.h"

#include "gmock/gmock.h"

#include "csubscriber.h"

#include "cpublisher.h"

#include "csubeventhandler.h"

#include "cpubeventhandler.h"

using ::testing::atleast;

using testing::return;

class mockcsubscriber : public csubscriber

mock_method1(readbuf, int(int len));

mock_method1(writebuf, int(int len));

mock_method0(closesock, void());

};class mockcpublisher : public cpublisher

mock_method1(readbuf, int(int len));

mock_method1(writebuf, int(int len));

mock_method0(closesock, void());

};test(subpubhandler, sub1pub1)

csubscriber的標頭檔案:

class csubscriber : public cbaseconnection, public chashelement

;

e)、main函式的寫法

與gtest相同,唯一的區別是初始化引數,如下:

#include int main(int argc, char** argv)

如此,就可以完整的使用googletest/googlemock做c++工程的單元測試了,確實很簡單好用。

用google mock模擬C 物件

google mock是用來配合google test對c 專案做單元測試的。它依賴於googletest 參見我上篇文章 如何用googletest寫單元測試 下面我來說說linux上怎麼用它來做單元測試。1 如何獲取 編譯google mock gmock的當前版本與gtest一樣,是1.6.0...

用c 模擬ATM機

一.題目 用c 模擬atm機.二.分析 實現atm機,首先要建立兩個類,乙個為使用者類,用來儲存使用者個人資訊。另乙個為atm類,用來實現各種功能。使用者類中使用者個人資訊只有使用者本人可以檢視,所以全部為私有資料成 員,包括使用者的密碼 使用者的卡號 使用者餘額 使用者名字。atm機類主要是實現登...

用C進行物件導向程式設計 用C模擬繼承,多型

最近在開發瀏覽器,程式語言是c。由於dom明顯是有層次結構,如 node textnode elment 用面向過程的c來開發,有點吃力。所以決定犧牲部分效能,用c模擬物件導向的開發,使程式的結構更加清晰一點。要考慮到問題 1.如何定義乙個類 包括考慮繼承性的問題,如何定義介面,如何定義成員 2.物...