模拟和Win32 API调用

7 c winapi unit-testing mocking

我正在使用的当前产品是用C++编写的Windows服务,并且所有新功能都将为其编写单元测试.但是这会产生一个有趣的问题(至少对我来说)我们会针对各种事情做很多Win32调用并相应地运行,所以为了完成单元测试,测试各种输出会很好,而不仅仅是当前系统州.

我的问题是模拟Win32调用结果的最佳方法是什么?我考虑过两种不同的方法:

1)将所有使用的Win32调用放入函数指针,并将它们传递给使用它们的函数或类(取决于它们被击中的次数)并使用它来获取模拟结果.

2)#ifdef UNITTEST到处都有很多,如果它正在调用我自己的特殊方法,或者如果没有,则调用正常的方法.

我完全偏离这里,还是错过了一个基本的知识?

Mat*_*ier 9

关于(2),大多数采用字符串参数的Win32函数已经将它们的公共格式定义为宏,例如来自WinUser.h:

WINUSERAPI
int
WINAPI
MessageBoxA(
    __in_opt HWND hWnd,
    __in_opt LPCSTR lpText,
    __in_opt LPCSTR lpCaption,
    __in UINT uType);
WINUSERAPI
int
WINAPI
MessageBoxW(
    __in_opt HWND hWnd,
    __in_opt LPCWSTR lpText,
    __in_opt LPCWSTR lpCaption,
    __in UINT uType);
#ifdef UNICODE
#define MessageBox  MessageBoxW
#else
#define MessageBox  MessageBoxA
#endif // !UNICODE
Run Code Online (Sandbox Code Playgroud)

你当然可以在你的项目中添加一个标题,重新定义你想要模拟的API函数:

#ifdef UNITTEST
#undef MessageBox
#define MessageBox UnitTestMessageBox
#endif
Run Code Online (Sandbox Code Playgroud)

通过重新定义名称,可以避免在整个源代码中散布大量条件编译.


小智 6

最后,我实际上更多地采用了类似 C# 的方法并创建了接口,使我能够消除我想要使用的 Win32 调用。

例如,我有一个IRegistryOperations名为RegOpenKey、的名称RegQueryValueExRegNotifyChange以及我正在使用的其他几个名称。在构造函数中创建了一个仅调用实际函数的默认函数,但我还有一个采用接口的构造函数,这样我就可以模拟狡猾的值等。

(不确定回答我自己的问题是否不礼貌)


fra*_*ast 5

我建议将 API 调用封装到精心设计的接口中。然后,您可以使用模拟对象或测试替身来测试您的业务逻辑。您不需要测试 Windows API 本身,因为数百万个正在运行的 Windows 应用程序已经完成了这项工作。

如果您不开发硬件,单元测试就不应该涉及硬件访问。这只是测试您的逻辑代码。