我開始爲C/C++項目使用CppUTest。特別是嘲笑擴展聽起來不錯,但我目前正在努力如何以正確的方式設置模擬。假設一個抽象網絡套接字通信的低級別類。CppUTest:如何將更多數據傳遞給特定的模擬調用?
我的第一種方法:
size_t CMockSocket::recv(void* buf, size_t len) { return (size_t) mock().actualCall("recv") .withParameter("len", (int) len) .returnValue().getIntValue(); }
設置的期望:
mock().expectOneCall("recv") .withParameter("len", 20) .andReturnValue(15);
到目前爲止好。但我需要的是提供更多數據 - 在這種情況下,我想通過buf指針返回15個字節。我試圖使用.setData()
和setDataObject()
方法。但它看起來像函數將數據存儲在命名變量中,而不是預期的函數調用。因此後續的調用會覆蓋前面的數據,對吧?
我目前的問題是我怎麼能通過額外的返回數據的嘲笑方法?我的第一個意見是創建一個包含返回值(size_t)和數據緩衝區的結果類。就像這樣:
class CRecvResults { public: size_t m_returnValue; void* m_buffer; CRecvResults(size_t returnValue, void* buffer) : m_returnValue(returnValue), m_buffer(buffer) {} ~CRecvResults() {} }; size_t CMockSocket::recv(void* buf, size_t len) { CRecvResults* pResults = (CRecvResults*) mock().actualCall("recv") .withParameter("len", (int) len) .returnValue().getPointerValue()); assert(pResults != NULL); assert(buf != NULL); assert(len >= pResults->m_buffer.length()); memcpy(buf, pResults->m_buffer.data(), pResults->m_buffer.length()); return pResults->m_returnValue; }
和期望:
char* buffer = "some returning buffer content at least 15 chars long"; CRecvResults results(15, buffer); mock().expectOneCall("recv") .withParameter("len", 20) .andReturnValue(&results);
問:這是正確的做法還是我錯過了什麼?我需要緩衝區內容,因爲我需要測試結果解釋器。
我的第二種方法:
bool CMockSocket::send(const void* buf, size_t len) { return mock().actualCall("send") .withParameter("len", (int) len) .returnValue().getIntValue(); }
設置的期望:
mock().expectOneCall("send") .withParameter("len", 20) .andReturnValue(true);
在這種情況下,我想驗證buf中輸出數據,由被測代碼生成的。因此我需要將該緩衝區內容(和長度)返回給測試函數。就像這樣:
class CSendResults { public: bool m_returnValue; char* m_buffer; size_t m_length; CSendResults(bool returnValue, char* buffer, size_t length) : m_returnValue(returnValue), m_buffer(buffer), m_length(length) {} ~CSendResults() {} }; bool CMockSocket::send(const void* buf, size_t len) { CSendResults* pResults = (CSendResults*) mock().actualCall("send") .returnValue().getPointerValue(); assert(pResults != NULL); assert(buf != NULL); assert(pResults->m_length >= len); memcpy(pResults->m_buffer, buf, len); pResults->m_length = len; return pResults->m_returnValue; }
和期望:
char buffer[1024]; CSendResults results(true, buffer, sizeof(buffer); mock().expectOneCall("send") .withParameter("len", 20) .andReturnValue(&results); // further checks for results content...
這看起來非常難看,用大量的開銷給我。我的問題再次出現:這是正確的方式,還是我錯過了什麼?
我的最後一個問題是:我能測試完全錯誤的方式嗎?請讓我知道你的經驗和做法!
那真是個好消息!我會盡快檢查,看起來像一個乾淨的解決方案。 – Andi 2015-04-29 12:17:53
順便說一句,在哪個版本中增加了這個功能? – Andi 2015-04-29 12:18:21
它存在於3.6版本中。從那以後,有很多改進,所以可能值得看看目前的頭像。 – 2015-04-29 13:42:41