當構造測試用例的數據,是在函數內部被另一個外部函數所使用時,我們需要忽略外部函數所帶來的影響。
需要進行“打樁”,舉一個具體的例子
class DataGetter { public: ... bool Run(); ... private: ... Client* m_ptr_client; ... }; ..... ..... bool DataGetter::Run() { ... std::string data; bool ret = m_ptr_client->GetData(data); ... } .... ....
比如要對run這個函數進行單元測試,它內部調用了ptr_client->GetData(data)的方法,它是通過tcp協議從服務端取數據到data裡,測試run這個函數,必然要構造data。
如果不“打樁”,要測試的話,我們就需要再從服務端去構造數據,而且還可能收到其他因素的影響。
這時候“樁”就是很好的一種技術。
那如何去構造“樁”呢。
原理:利用c++ virtual的特性,改變m_ptr_client指針所指向的對象,重寫一個“打樁”測試類。
當然,前提是GetData的定義本身是virtual的。
假設Client的定義如下
class Client { ...... public: virtual bool GetData(std::string& data); ...... };
我們只需要重寫Getdata的方法,並且當參數data被傳進來時,我們可以返回特定的值。
這一套方法,google已經提供了很好的一套框架:gmock
下面介紹一下它的用法
#include "client.h" //被mock的類的頭文件 #include// gmock 的頭文件 class MockClient : public Client { public: MockClient():Client() {} MOCK_METHOD1(GetData, bool(std::string&)); }
這裡使用了一個宏MOCK_METHOD1
原形是MOCK_METHOD#1(#2, #3(#4) )
#1表示被mock的函數參數個數,#2表示被mock的函數名稱,#3表示被mock的函數返回值,#4表示被mock的函數參數列表
這樣,一個“樁”就“打”好了。
首先,要先改變m_ptr_client指向的對象,對於private的變量,在前一章有描述方法,
然後測試的時候,直接將 m_ptr_client = new MockClient()即可,不過要記得釋放它之前new的資源(如果有的話),不然就內存洩露了,哈哈
使用gmock的幾個宏,用一個例子簡單介紹下:
EXPECT_CALL( //mock被調用時,要發生的動作 *m_ptr_client, // 被mock的對象,看清楚,是對象,不是指針了 GetData(test::_) // 被mock的方法,參數為占位符 ).Times(2) // 表示被調用2次 .WillOnce( 第一次調用 testing::SetArgReferee<0>(“test”), //設置第0個參數的值為“test” testing::Return(true), //設置返回值為true ) .WillOnce( 第二次調用 testing::SetArgReferee<0>(“test”), //設置第0個參數的值為“test” testing::Return(false), //設置返回值為false );
測試的原則,盡量不修改被測函數,覆蓋函數的每一個分支,保證外部條件都是正確的。
參考文檔:
http://blog.csdn.net/russell_tao/article/details/7344739