【问题标题】:Stubbing WinBase.h in cppunit test在 cppunit 测试中存根 WinBase.h
【发布时间】:2015-06-14 23:24:30
【问题描述】:

我正在为使用命名管道的类编写单元测试。我需要存根 CreateNamedPipe、ConnectNamedPipe、WriteFile、ReadFile、FlushFileBuffers、DisconnectNamedPipe、CloseHandle 和 GetLastError

这些都在 WinBase.h 中定义为 dll 导入。

不幸的是,WinBase.h 是一个无处不在的巨大文件,因此不能仅仅将要测试的项目存根...

我尝试复制 WinBase.h 并制作函数的内联版本:

bool
ConnectNamedPipe(
    __in        HANDLE hNamedPipe,
    __inout_opt LPOVERLAPPED lpOverlapped
    )
{ return false; }

但是对于每个被覆盖的函数/对象对,我都会遇到编译错误:

3>test.obj : error LNK2005: ReadFile already defined in main.obj

Main 非常小,但确实包含

#include <file_templates/cppunit/generic_cppunit_main.cpp>

这很可能在其深处的某个地方包含 WinBase.h...

即使我解决了这个编译错误,我也有可能在这个过程中破坏 cppunit?

是否有没有抽象出所有管道调用并存根抽象而不是 WinBase.h 的解决方案?

【问题讨论】:

  • 如果您想在头文件中提供内联实现,您可以,但您需要使用inline 关键字声明这些函数。否则你会得到链接器错误。
  • 您需要让链接器满意。它不会喜欢从两个 .lib 文件中选择一个最喜欢的。但是您不会遇到 ReadFile 存在于 .obj 文件中的问题,它会首先选择那个。

标签: c++ unit-testing named-pipes cppunit


【解决方案1】:

在我看来,通过抽象重定向消除几乎是最好的方法,让您尽可能多地保持理智。完全使用预处理器可以做到这一点,并且没有运行时开销。只需在您的课程中使用以下设计模式:

#ifndef MY_CREATE_NAMED_PIPE
#define MY_CREATE_NAMED_PIPE CreateNamedPipe
#endif

#ifndef MY_CONNECT_NAMED_PIPE
#define MY_CONNECT_NAMED_PIPE ConnectNamedPipe
#endif

...等等。然后,让您的代码使用它们的#defined 别名调用系统调用。

随意使用您喜欢的任何 munging 约定。

然后,在您的单元测试模块中:

#define MY_CREATE_NAMED_PIPE my_create_named_pipe
#define MY_CONNECT_NAMED_PIPE my_connect_named_pipe

// And so on, then include your source module directly:

#include "source.cpp"

然后您的单元测试模块将实现 my_create_named_pipe() 存根等。本质上,您最终会为您的单元测试构建一个单独的源模块副本,除了被调用的系统调用的名称外,它在各方面都是相同的。

【讨论】:

  • 存根版本也应该是全局的?没有 .h 文件?
  • 存根版本当然可以是静态的,在您的单元测试模块中。而你包含 cpp 的原因是因为如果你不这样做,这一切都不会奏效。再读一遍我的答案。
  • 显然某些地方必须包含一些东西,但正常的模式是包含一个标头并单独编译 cpp。按照你的建议做会让我出现链接器错误。我想我需要像头文件那样包含多重包含保护。错误 2 错误 LNK2005: "bool __cdecl ConnectNamedPipeStub(void *,void *)" (?ConnectNamedPipeStub@@YA_NPEAX0@Z) 已在 pipe_stubs.obj ...test.obj 中定义
  • 啊。对,我不应该同时编译 pipe_stubs.cpp 并包含它。
  • 我最终得到了您设计的一个变体。我有一个 .h 文件,在生产中指的是 WinBase.h 函数,但在测试中指的是新函数。新函数的原型在 .h 文件中,但在 cpp 文件中实现。编译中的 cpp 为独立对象,不包含在测试中。我可以使用 extern 或 setter 函数来影响存根的行为。
猜你喜欢
  • 2011-03-05
  • 2011-12-31
  • 1970-01-01
  • 1970-01-01
  • 2013-07-27
  • 2010-11-04
  • 2010-09-22
  • 2022-06-29
  • 1970-01-01
相关资源
最近更新 更多