动态dll加载和googletest

6

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

我需要尽可能少地进行操作,所以我的计划是:

  1. add test files to each of library and link it against gmock.lib
  2. prepare a single executable which would load dynamically desired dll with minimal main() like this:

    int main(int argc, char** argv)
    { 
        LoadLibrary(argv[1]);
        testing::InitGoogleMock(&argc, argv);
    
        const int status = RUN_ALL_TESTS();
    
        return status;
    }
    
问题在于,从加载的库中获取的测试对于我的exe文件不可见(可以确定已经加载和初始化了dll)。输出如下:
[==========] Running 0 tests from 0 test cases.
[==========] 0 tests from 0 test cases ran. (0 ms total)
[  PASSED  ] 0 tests.

看起来我应该将dll文件中的测试引入exe中,但我找不到任何信息。我的方法是否正确?或者还有其他简单的方法吗?

1个回答

6
编译时确定将要执行的测试。你所做的只是在运行时使用显式DLL加载(函数LoadLibrary)将DLL加载到进程地址空间中。
首先,我建议您根本不要在DLL项目中添加测试。没有必要将单元测试代码放在将部署给最终用户的DLL中。另一个问题是,当您使用显式DLL加载时,必须显式检索DLL中函数的地址并使用它来调用该函数:

https://msdn.microsoft.com/en-us/library/784bt7z7.aspx

这不适合你想要的。你应该做以下操作:
  1. 向项目中添加测试(使用所有所需DLL中的函数),以构建可执行文件,从而运行来自所有DLL的单元测试。
  2. 将函数和类的头文件路径(从所有所需DLL中)作为附加包含目录添加到构建此可执行文件的项目中。
  3. 将此可执行文件链接到 gmock.lib
  4. 使用 dllimport 存储类属性设置隐式DLL加载,因此您无需编写明确获取用于单元测试中使用的DLL中函数地址的代码。

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

https://msdn.microsoft.com/en-us/library/d14wsce5.aspx

编辑:

由于对于您来说切换到隐式链接不是一个选项,因此请按照以下方式修改您的方法:

首先,在每个DLL中添加一个额外的导出函数,用于运行单元测试:

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

然后,在您的可执行文件的主函数中,循环遍历所有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);
    }
}

谢谢您的回答。您的解决方案有一些缺点:1. Dlls 由成千上万个类和函数组成,我无法使它们全部可见,使得 exe 文件中的测试可以使用它们全部。2. 在 Visual Studio 中为每个 dll 创建单独的 exe 项目可能不是正确的方法。对我来说,在 dll 中进行测试很好,因为在发布版本中根本不会编译测试。 - Michał Walenciak
1
@MichałWalenciak 1. 我并不知道这是情况,我已经编辑了我的答案,针对单元测试在DLL中的情况。2. 我并不是想建议你为每个DLL创建一个单独的exe文件。然而,我的回答并没有表达清楚,所以我理解你为什么会认为我是在建议这样做。我也编辑了答案的这部分内容,以澄清这一点。 - Marko Popovic
2
@MichałWalenciak 请注意另一件事。我知道在你的情况下将单元测试保留在DLL中是最好的方法,但仅在Debug模式下运行测试可能会导致一些微妙的错误。考虑定期以Release模式构建单元测试并运行它们以确保安全。 - Marko Popovic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接