如何使用google test / mock测试基于MFC CWnd的类?

时间:2016-04-28 17:47:29

标签: c++ unit-testing mfc mocking googletest

我对TDD这个想法很新。我之前没有使用过任何测试框架。最近我开始阅读它并练习谷歌测试。 我的目标是在MFC开发的遗留代码库中启动TDD。大多数时候我必须使用GUI控件 - 开发新的自定义控件,向现有的自定义控件添加功能等。所以,我想自动化测试主要来自CWnd类的GUI类。

我在Visual Studio中创建了一个用于测试的win32控制台项目,在创建项目时,我已经勾选了MFC,并为'添加了常用的头文件。选项。 Visual Studio项目向导已生成main函数并已创建CWinApp对象。在主要功能中,我添加了谷歌测试的样板代码。我已经将实际项目(即要测试)和google test(和mock)库编译为.lib并将其链接到测试项目。我已经成功构建了测试项目。我可以从项目中测试简单的东西。

这是向导生成的代码(包括谷歌测试样板代码) -

#include "stdafx.h"
#include "TestMFC.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// The one and only application object
CWinApp theApp;
using namespace std;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    int nRetCode = 0;

    HMODULE hModule = ::GetModuleHandle(NULL);

    if (hModule != NULL)
    {
        // initialize MFC and print and error on failure
        if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
        {
            // TODO: change error code to suit your needs
            _tprintf(_T("Fatal Error: MFC initialization failed\n"));
            nRetCode = 1;
        }
        else
        {
            // TODO: code your application's behavior here.
              testing::InitGoogleMock(&argc, argv);
              nRetCode = RUN_ALL_TESTS();
        }
    }
    else
    {
        // TODO: change error code to suit your needs
        _tprintf(_T("Fatal Error: GetModuleHandle failed\n"));
        nRetCode = 1;
    }
    return nRetCode;
}

我面临的挑战是我无法创建实际窗口,因为这需要有消息循环。我想模仿CWnd,以便我可以根据已知的假设测试功能。但是,我无法找到一种模拟CWnd的方法,因为它有一些依赖于HWND的非虚拟成员函数。 HWND仅在我创建窗口时有效。另一个挑战是消息处理程序不是虚函数。因此,我无法模拟消息处理程序,也无法创建窗口,因此无法将消息路由到其处理程序。

我需要思考如何解决问题。我可以不用mock或其他东西创建实际窗口吗?或者我可以创建窗口和路由消息?

提前致谢。

3 个答案:

答案 0 :(得分:1)

我建议使用 Visual Studio Coded UI Test Automation 套件。它比Google Mock要好得多。 Visual Studio Coded UI Test本身支持MFC / Win32 GUI。

答案 1 :(得分:0)

测试MFC应用程序时出现问题,因为大多数功能未导出。所以我们应该在GTEST项目中包含我们的源代码并将其与MFC运行时链接起来。这是棘手的部分。我在NuGet包中使用了VS2017“测试适配器进行Google测试”:my project中的“googletest.v140.windesktop.static.rt-dyn”终于可以使用了。

答案 2 :(得分:0)

可能需要mfc和消息循环。从Visual Studio向导生成的应用程序开始,并覆盖CWinApp的InitInstance,OnIdle和ExitInstance虚拟功能,将更加容易。

您可能需要允许通过MainWindow传递Windows消息,因此这使您能够具有运行测试的有限状态机(FST)。我在InitInstance中初始化了我的环境,并从ExitInstance报告了测试结果。我主要使用FST来设置下一个测试验证器(一个函数指针)(要从被测对象正在执行的操作中调用),并调用一个测试启动器函数来发送消息以启动下一个动作。

我使用OnIdle开始测试,因为只有在MFC系统稳定和设置好之后才一直调用它。

使用googletest或Boost测试或更旧版本的Visual Studio的缺点是单元测试框架希望驱动测试。它们不允许您提供FST来运行测试。我将代码存储在DLL中时遇到问题(全局函数不在不同DLL中查看相同的全局地址空间-有关DLL中的Singleton模式问题)。