代码之家  ›  专栏  ›  技术社区  ›  user1333

模拟和Win32 API调用

  •  7
  • user1333  · 技术社区  · 15 年前

    我目前工作的产品是一个用C++编写的Windows服务,未来所有的新功能都会为它编写单元测试。但这就产生了一个有趣的问题(至少对我来说),我们对各种事物进行了大量的win32调用,并相应地进行操作,因此,要完成单元测试,最好测试各种输出,而不仅仅是当前的系统状态。

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

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

    2)有很多 #ifdef UNITTEST 在任何地方,如果它调用了我自己的特殊方法,或者调用了正常方法。

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

    5 回复  |  直到 7 年前
        1
  •  9
  •   Matthew Xavier    15 年前

    关于(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
    

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

    #ifdef UNITTEST
    #undef MessageBox
    #define MessageBox UnitTestMessageBox
    #endif
    

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

        2
  •  4
  •   frast    15 年前

    我建议将API调用封装到分解良好的接口中。然后,您可以使用模拟对象或测试双重对象来测试业务逻辑。您不需要测试Windows API本身,因为这已经由数百万工作的Windows应用程序完成。

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

        3
  •  2
  •   i_am_jorf    15 年前

    使用 Deviare API 钩住并拦截所有API调用,并进行单元测试。

        4
  •  2
  •   Ajay    7 年前

    最后,我采用了更接近C的方法,并创建了一些接口,使我能够消除我想要使用的win32调用。

    例如,我有一个电话 IRegistryOperations 包含的 RegOpenKey , RegQueryValueEx , RegNotifyChange 还有其他几个我用的。在构造函数中创建了一个简单地调用实际函数的默认构造函数,但我也有一个采用接口的构造函数,这样我就可以模拟不可靠的值等。

    (不知道回答我自己的问题是否不礼貌)

        5
  •  -1
  •   Brian R. Bondy    15 年前

    如果可能,最好在不修改Win32调用的情况下使事件发生。

    例如,不要自己做 CreateFile 这将失败,因为一个文件正在使用中,而是用另一个程序(您从单元测试调用的程序)以独占方式打开该文件,然后运行单元测试。

    如果您必须模拟一些Win32调用,那么最好围绕您要进行的Win32调用集创建一个包装库。那么你就不会损害代码识字的主要逻辑。