我开始将 CppUTest 用于一些 C/C++ 项目。特别是模拟扩展听起来不错,但我目前正在努力如何以正确的方式设置模拟。假设一个用于抽象网络套接字通信的低级类。
我的第一种方法:
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()
andsetDataObject()
方法。但看起来函数将数据存储在命名变量中,而不是使用预期的函数调用。因此后续调用将覆盖前面的数据,对吗?
我目前的问题是如何将额外的返回数据传递给模拟方法?我的第一个方法是创建一个包含返回值(size_t)和数据缓冲区的结果类。像这样:
类 CRecvResults { 上市: size_t m_returnValue; 无效* m_buffer; CRecvResults(size_t returnValue, void* buffer) : m_returnValue(returnValue), m_buffer(缓冲区) {} ~CRecvResults() {} }; size_t CMockSocket::recv(void* buf, size_t len) { CRecvResults* pResults = (CRecvResults*) mock().actualCall("recv") .withParameter("len", (int) len) .returnValue().getPointerValue()); 断言(pResults!= NULL); 断言(buf!= NULL); 断言(len >= pResults->m_buffer.length()); memcpy(buf, pResults->m_buffer.data(), pResults->m_buffer.length()); 返回 pResults->m_returnValue; }
和期望:
char* buffer = "一些返回的缓冲区内容至少 15 个字符长"; CRecvResults 结果(15,缓冲区); 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(); }
设置期望:
模拟().expectOneCall(“发送”) .withParameter("len", 20) .andReturnValue(true);
在这种情况下,我想验证由被测代码生成的 buf 中的传出数据。因此,我需要将该缓冲区内容(和长度)返回给测试函数。像这样:
CSendResults 类 { 上市: 布尔 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(); 断言(pResults!= NULL); 断言(buf!= NULL); 断言(pResults->m_length >= len); memcpy(pResults->m_buffer, buf, len); pResults->m_length = len; 返回 pResults->m_returnValue; }
和期望:
字符缓冲区[1024]; CSendResults 结果(真,缓冲区,sizeof(缓冲区); 模拟().expectOneCall(“发送”) .withParameter("len", 20) .andReturnValue(&results); // 进一步检查结果内容...
这看起来很丑陋,对我来说有很多开销。再次我的问题:这是正确的方法还是我错过了什么?
我的最后一个问题是:是不是我测试的方式完全错误?请告诉我您的经验和做法!