首页 文章

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

提问于
浏览
2

我开始在一些C / C项目中使用CppUTest . 特别是 Mock 扩展声音很好,但我目前正在努力如何以正确的方式设置模拟 . 假设用于抽象网络套接字通信的低级类 .

My first method:

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);

问题:这是正确的方式还是我错过了什么?我需要缓冲区内容,因为我需要测试结果解释器 .

My second method:

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...

这看起来非常丑陋,对我来说有很多开销 . 我的问题再一次:这是正确的方式还是我错过了什么?

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

2 回答

  • 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 的内容将通过输出参数复制到模拟的调用者 . 因此不再需要丑陋的解决方法 .

  • 0

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

    这样,所需的附加数据被绑定到函数调用的参数列表 .

    Foltos

相关问题