CppUTest:如何将更多数据传递给特定的模拟调用?

Posted

技术标签:

【中文标题】CppUTest:如何将更多数据传递给特定的模拟调用?【英文标题】:CppUTest: how to pass more data to a specific mock call? 【发布时间】:2013-02-21 00:53:02 【问题描述】:

我开始在一些 C/C++ 项目中使用 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)和数据缓冲区的结果类。像这样:

类 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); // 进一步检查结果内容...

这看起来很丑陋,而且对我来说开销很大。我的问题又是:这是正确的方法还是我错过了什么?

我的最后一个问题是:我的测试方式是否完全错误?请告诉我您的经验和做法!

【问题讨论】:

【参考方案1】:

我正在使用以下丑陋的解决方法。 我为返回值定义了一个结构类型以及我在假函数中需要的附加数据。 我分配并填充了一个调用expectOneCall() 的实例,并使用“.andReturnValue()”传递它。在假函数中,我使用“...returnValue().getPointerValue()”获取数据,然后将返回值设置为 struct->rc,并处理我的附加数据(将其复制/比较到缓冲区)。在退出假函数之前,结构被释放。

这样将需要的附加数据绑定到函数调用的参数列表中。

Foltos

【讨论】:

感谢 Foltos 的评论。我看到我们有使用自定义结构/对象的类似方法。随着上个月的更多经验,我的印象是这种情况不会经常出现。我尝试查看其他 xUnit 框架如何处理此问题,但没有找到更通用的解决方案。【参考方案2】:

CppUTest 中添加了一项新功能,可让您为模拟指定输出参数。这可能是这样的:


    return (size_t) mock().actualCall("recv")
        .withOutputParameter("buf", buf)
        .withParameter("len", (int) len)
        .returnUnsignedLongIntValueOrDefault(0);

期望可以这样指定:

char buffer[] = "blabla";

mock().expectOneCall("recv")
    .withOutputParameterReturning("buf", buffer, sizeof(buffer))
    .withParameter("len", sizeof(buffer))
    .andReturnValue(sizeof(buffer));

buffer 的内容将通过输出参数复制到模拟的调用者。所以不再需要丑陋的解决方法。

【讨论】:

好消息!我很快就会检查它,看起来像一个干净的解决方案。 顺便说一句,这个功能是在哪个版本添加的? 它出现在 3.6 版中。从那以后已经有了很多改进,所以可能值得看看当前的负责人。 3.7版发布 太棒了!我等了很久。我必须阅读文档才能看到所有新内容。

以上是关于CppUTest:如何将更多数据传递给特定的模拟调用?的主要内容,如果未能解决你的问题,请参考以下文章

Postman、Python 以及将图像和元数据传递给 Web 服务

微信小程序如何将接口获取的数据传递给自定义组件

将动态数据传递给引导模式

将动态数据传递给引导模式

从数据库加载用户特定设置和站点设置并将数据传递给视图和控制器

如何将数据传递给BottomSheetDialogFragment [重复]