动态dll加载和googletest

Mic*_*iak 5 c++ dll googletest

我有几个基于MFC的项目(DLL)。我想在其中添加一些GTest / GMock测试。

我需要用最小的efford来做,所以总体计划是:

  1. 将测试文件添加到每个库,并将其链接到gmock.lib
  2. 准备一个可执行文件,以最小的main()动态加载所需的dll,如下所示:

    int main(int argc, char** argv)
    { 
        LoadLibrary(argv[1]);
        testing::InitGoogleMock(&argc, argv);
    
        const int status = RUN_ALL_TESTS();
    
        return status;
    }
    
    Run Code Online (Sandbox Code Playgroud)

问题是从加载的库进行的测试对我的exe文件不可见(肯定会加载并初始化dll)。输出为:

[==========] Running 0 tests from 0 test cases.
[==========] 0 tests from 0 test cases ran. (0 ms total)
[  PASSED  ] 0 tests.
Run Code Online (Sandbox Code Playgroud)

似乎我应该以某种方式将测试从dll文件引入exe,但找不到任何信息。我的方法可以吗?也许还有其他简单的方法?

Mar*_*vic 5

将在编译时确定将要执行的测试。您要做的只是LoadLibrary在运行时使用显式DLL加载(函数)将DLL加载到进程地址空间中。

首先,我建议您根本不要将测试添加到DLL项目中。不需要将单元测试代码放在DLL中,该DLL将被部署给最终用户。另一个问题是,当您使用显式DLL加载时,必须从DLL中显式检索函数的地址并使用它来调用该函数:

https://msdn.microsoft.com/zh-CN/library/784bt7z7.aspx

这不适合您的需求。您应该执行以下操作:

  1. 将测试(使用所有所需DLL中的功能)添加到项目中,该项目将构建可执行文件,该可执行文件将运行所有DLL中的单元测试。
  2. 添加函数和类的头文件路径(来自所有所需的DLL),作为构建此可执行文件的项目的其他包含目录。
  3. 将此可执行文件链接到 gmock.lib
  4. 使用dllimport存储类属性设置隐式DLL加载,因此您不必编写从DLL中显式获取函数地址的代码,这些代码将在单元测试中使用。

有关隐式DLL加载的更多信息,请参见:

https://msdn.microsoft.com/zh-CN/library/d14wsce5.aspx

编辑:

由于切换到隐式链接不是您的选择,因此请按照以下方式修改方法:

首先,向每个DLL添加一个附加的导出功能,该功能运行单元测试:

void runTests(int argc, char *argv[])
{
    testing::InitGoogleMock(&argc, argv);
    const int status = RUN_ALL_TESTS();
}
Run Code Online (Sandbox Code Playgroud)

然后,在可执行文件的主要功能中,循环访问所有DLL,并使用以下命令对每个DLL执行此导出的功能:

HMODULE hDLL = LoadLibraryA("MyDLL");
if(hDLL != NULL)
{
    fpRunTests runTestsFun = (fpRunTests)GetProcAddress(hDLL, "runTests");
    if(!runTestsFun)
    {
        // Handle the error
        FreeLibrary(hDLL);
    }
    else
    {
        // Call the function which runs tests
        runTestsFun(argc, argv);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @MichałWalenciak 请注意一件事。我知道在 DLL 中保留单元测试是针对您的情况的最佳方法,但始终在调试模式下运行测试只会导致一些微妙的错误被忽略。为了安全起见,请考虑时不时地在发布模式下构建单元测试并运行它们。 (2认同)