c++ - googletest测试框架c++:静态方法链接器错误

标签 c++ visual-studio-2010 testing linker-errors googletest

我正在尝试从我的TEST中调用静态方法,但是却遇到了无法解析的外部符号。
到目前为止,我所做的是:
创建了3个项目:


将GoogleTest项目作为静态库-编译了gtest-all.cc和gtest_main.cc
MyProject-我保存.h和.cpp文件的位置
UnitTest项目-我保存测试的地方


我已经设置了UnitTest的其他目录,lib目录,并引用了GoogleTest和MyProject。测试运行良好,直到我从一个类中调用静态方法为止。

链接器选项:

/OUT:"D:\SkyDrive\Projekti\Visual Studio 2010\Projects\File System\Debug\Unit Test.exe" /INCREMENTAL /NOLOGO "..\lib\part.lib" "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" "D:\SkyDrive\Projekti\Visual Studio 2010\Projects\File System\Debug\Google Test.lib" /MANIFEST /ManifestFile:"Debug\Unit Test.exe.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\SkyDrive\Projekti\Visual Studio 2010\Projects\File System\Debug\Unit Test.pdb" /SUBSYSTEM:CONSOLE /PGD:"D:\SkyDrive\Projekti\Visual Studio 2010\Projects\File System\Debug\Unit Test.pgd" /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:QUEUE


错误:

error LNK2019: unresolved external symbol "public: static char __cdecl FS::mount(class Partition *)" (?mount@FS@@SADPAVPartition@@@Z) referenced in function "private: virtual void __thiscall Cluster_KernelFS_mountPartition_Test::TestBody(void)" (?TestBody@Cluster_KernelFS_mountPartition_Test@@EAEXXZ)   D:\SkyDrive\Projekti\Vi‌​sual Studio 2010\Projects\File System\Unit Test\cluster.obj

最佳答案

从我们的意见交流中可以明显看出,您与您的联系
googletest单元测试项目(Unit Test)不包含由应该测试的项目(MyProject)生成的必要对象文件。 fs.obj
kernelfs.obj至少有两个缺失,并且通过检查
链接器命令行失败时,似乎您没有链接任何目标文件
实现您要测试的类或函数(如果还有)

您似乎相信,将对MyProject的Visual Studio项目引用添加到Unit Test会自动为Unit Test提供缺少的目标文件依赖关系,但不会。

消除链接错误的最快方法是将MyProject生成的缺少的目标文件添加到Unit Test项目的配置属性->链接器->输入->其他依赖项中。

您可以通过一个完全限定的路径名​​来添加每个丢失的.obj文件
放在DebugMyProject输出目录中。或者更容易地,您可以将Debug目录的路径添加到“配置属性”->“链接器”->“输入”->“其他目录”,然后只需将缺少的.obj文件的标准名称添加到“其他依赖项”。

但这将是一个有缺陷的解决方案,因为您当然希望Unit Test始终
基于最新版本的MyProject,而不仅仅是任何MyProject对象
文件恰好在当时存在。在这种情况下,您有两种选择:


a)您可以将生成丢失的.obj文件的源文件以及Unit Test添加到MyProject项目。在Unit Test的“解决方案资源管理器”视图中,右键单击“源文件”,然后导航“添加”->“现有项”。在这种情况下,您必须注意,每当将新的源文件添加到MyProject时,也要将其添加到Unit Test
b)此选项假定两个项目都在同一解决方案中。如果不是你
可以使它们如此。然后,您可以首先执行快速但有缺陷的解决方案(并对其进行测试)。然后,为了修复该缺陷,可以使Unit Test依赖于MyProject,这样,无论何时构建Unit Test,如果过时了,将自动首先构建MyProject。要创建此依赖关系,请在“解决方案资源管理器”窗格中右键单击Unit Test,浏览“构建依赖关系”->“项目依赖关系”->“依赖关系”,然后选中复选框,以使Unit Test依赖于MyProject。在这种情况下,必须注意,每当.obj生成新的MyProject文件时,都应将其添加到Unit Test的其他链接程序依赖项中。


(b)是更好的做法。

以上所有假设均已正确配置Unit Test,以便编译器搜索MyProject的包含目录并正确定位其头文件。您似乎对该分数没有任何构建错误。

后续问题1


  您能否向我解释为什么链接程序不链接MyProject中的任何对象文件(我必须手动添加它们)。


就Visual Studio而言,MyProjectUnit Test只是两个项目
包含在构建不同可执行文件的相同解决方案中。它并不“知道” Unit Test的目的是对MyProject进行单元测试,因此需要链接MyProject生成的所有包含Unit Test要测试功能的目标文件。那么,为什么它会自动将MyProject的目标文件添加到Unit Test的链接中?

即使Visual Studio确实以某种方式知道Unit Test的目的是对MyProject进行单元测试,它如何知道应该在MyProject中链接哪个Unit Test对象文件?其中一个可能包含main()函数-实际上,如果MyProject构建控制台应用程序就是这种情况-但Unit Test还在其目标文件之一中生成main()函数;因此,不可能链接MyProject中的所有Unit Test对象文件:这将导致multiply defined symbol错误。

我指出,给Unit Test一个对My Project的项目引用不会将所有My Project的目标文件添加到Unit Test的链接中。您现在看到一个
之所以不能产生这种效果的原因。

这就是一个更普遍的原因:当您链接目标文件以构建可执行文件时,同一符号在多个目标文件中可见是一种链接错误。应该连接哪一个?但是,当然,在不同的可执行文件的链接中看到相同的符号并不是任何错误。这意味着您不能简单地从一个可执行文件的链接中搜出一堆目标文件,然后将它们添加到另一个可执行文件的链接中,并期望它起作用。如果要将目标文件从一个可执行文件添加到另一个可执行文件的链接中,则必须知道可以链接某些此类混合文件以及所需的混合文件。您必须知道要从哪个目标文件链接哪些符号,以使第二个可执行文件生效,然后选择
目标文件。正如您所说,这是“手动”练习。

如果MyProject生成了库而不是可执行文件,Visual Studio的项目参考功能将为您提供帮助。在这种情况下,创建从Unit TestMyProject的引用(除其他事项外)将告诉Visual Studio默认情况下,MyProject库将添加到Unit Test的链接中。与普通对象文件不同,创建库的目的是与不同的可执行文件链接,因此,MS Project参考功能很自然地支持库依赖关系的自动化。当然也可以假设,如果一个项目生成一个可执行文件,而不是一个库,那么它的目标文件只是一个副产品,并不打算与其他可执行文件链接。

组织工作的教科书方式将在三个项目中进行:


MyLib,生成包含要进行单元测试的所有功能的库。
MyProject,生成与当前相同的可执行文件,但链接MyLib
Unit Test,生成对MyLib进行单元测试的可执行文件,也链接MyLib


后续问题2


  向我解释如何配置链接器以从MyProject的调试文件夹链接.objs?


我已经有了。第4段,“或更容易...”等。您无法避免
指定要链接的单个.obj文件。您不能指示链接器“仅链接在/path/to/MyProject/Debug中找到的任何目标文件”,因为基于我已解释的原因,链接器的工作并不那么草率。

关于c++ - googletest测试框架c++:静态方法链接器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23042424/

相关文章:

用mingw编译的c++文件不打印hello world

c++ - 使用范围解析运算符时的语法错误

c# - 更改程序集名称破坏了我的 XAML 设计器

android - 将自定义应用程序与 InstrumentationTestCase 一起使用

c++ - 乒乓 Racket 未按预期运行

c++ - constexpr 上下文中的 std::optional 赋值运算符

c++ - VS 2010 无法打开源文件 "string"

.net - Resharper 不能很好地与 XAML 配合使用?

java - 使用不同 bean 运行单元测试的正确方法

java - EasyMock 记录阶段模拟作为参数