使用 Visual Studio C++ 进行单元测试时出现链接器错误

Linker error while unit testing with Visual Studio C++

我想用 Visual Studio 对我的 C++ 项目进行单元测试。从我的项目中添加文件夹作为我的测试项目的包含路径后,我在尝试编译测试时遇到链接器错误:

Severity    Code    Description Project File    Line    Suppression State
Error   LNK2019 unresolved external symbol "public: __thiscall Piece::Piece(enum Color)" (??0Piece@@QAE@W4Color@@@Z) referenced in function "public: __thiscall Bishop::Bishop(enum Color)" (??0Bishop@@QAE@W4Color@@@Z)    ChessPlusPlus-Tests D:\Documents\Projects\ChessPlusPlus\ChessPlusPlus-Tests\BishopTests.obj 1   
Error   LNK2019 unresolved external symbol "public: __thiscall Board::~Board(void)" (??1Board@@QAE@XZ) referenced in function "public: void __thiscall ChessPlusPlusTests::BishopTests::ValidMovesTest(void)" (?ValidMovesTest@BishopTests@ChessPlusPlusTests@@QAEXXZ)  ChessPlusPlus-Tests D:\Documents\Projects\ChessPlusPlus\ChessPlusPlus-Tests\BishopTests.obj 1   
Error   LNK2019 unresolved external symbol "public: void __thiscall Board::placePieceAt(class Piece * const,struct Position)" (?placePieceAt@Board@@QAEXQAVPiece@@UPosition@@@Z) referenced in function "public: void __thiscall ChessPlusPlusTests::BishopTests::ValidMovesTest(void)" (?ValidMovesTest@BishopTests@ChessPlusPlusTests@@QAEXXZ)    ChessPlusPlus-Tests D:\Documents\Projects\ChessPlusPlus\ChessPlusPlus-Tests\BishopTests.obj 1   
Error   LNK2001 unresolved external symbol "public: virtual class std::vector<struct Position,class std::allocator<struct Position> > __thiscall Bishop::getMovesFor(struct Position,class Board &)" (?getMovesFor@Bishop@@UAE?AV?$vector@UPosition@@V?$allocator@UPosition@@@std@@@std@@UPosition@@AAVBoard@@@Z)   ChessPlusPlus-Tests D:\Documents\Projects\ChessPlusPlus\ChessPlusPlus-Tests\BishopTests.obj 1   
Error   LNK2001 unresolved external symbol "public: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall Bishop::toString(void)" (?toString@Bishop@@UAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ)    ChessPlusPlus-Tests D:\Documents\Projects\ChessPlusPlus\ChessPlusPlus-Tests\BishopTests.obj 1   
Error   LNK2001 unresolved external symbol "public: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall Bishop::toShortString(void)" (?toShortString@Bishop@@UAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ)  ChessPlusPlus-Tests D:\Documents\Projects\ChessPlusPlus\ChessPlusPlus-Tests\BishopTests.obj 1   

我的测试源码:

#include "stdafx.h"
#include "CppUnitTest.h"
#include "Bishop.h"
#include "Board.h"
#include "TestUtils.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace ChessPlusPlusTests
{
    TEST_CLASS(BishopTests)
    {
    public:

        TEST_METHOD(ValidMovesTest)
        {
            // Arrange
            Board board{};
            Bishop *piece = new Bishop{ Color::WHITE };
            Position pos{ 3,3 };
            board.placePieceAt(piece, pos);

            // Act
            auto validPositions = piece->getMovesFor(pos, board);

            // Assert
            TestUtils::AssertPositions(validPositions, {
                0,0,0,0,0,0,0,1,
                1,0,0,0,0,0,1,0,
                0,1,0,0,0,1,0,0,
                0,0,1,0,1,0,0,0,
                0,0,0,0,0,0,0,0,
                0,0,1,0,1,0,0,0,
                0,1,0,0,0,1,0,0,
                1,0,0,0,0,0,1,0,
            });
        }

    };
}

如果不添加包含路径,测试项目将无法编译,因为主项目中包含的头文件依赖于包含路径。

主项目编译正常。

有人可以帮助我了解出了什么问题吗?

谢谢!

https://www.codeproject.com/Tips/1085171/How-To-Do-Unit-Testing-with-Cplusplus-in-Visual-St

我发现您还必须将 .h 和 .cpp 文件作为现有文件添加到测试项目中。这在官方文档中被遗漏了,或者我错过了。

现在可以了!

我只是 运行 遇到了同样的问题,并以不同的方式解决了它,遵循这篇 Microsoft 文档:https://docs.microsoft.com/nl-nl/visualstudio/test/unit-testing-existing-cpp-applications-with-test-explorer?view=vs-2015&redirectedfrom=MSDN#objectRef

我认为这个解决方案更简洁一些,因为您最终不会让被测项目的所有 header 文件也出现在您的测试项目中。

文档中的斜体行,粗体行是我添加的内容:

如果被测代码没有导出你要测试的功能,你可以将输出的.obj或.lib文件添加到测试项目的依赖中。

创建一个 C++ 测试项目。

在“文件”菜单上,依次选择“新建”、“项目”、“Visual C++”、“测试”、“C++ 单元测试项目”。

确保将要测试的项目添加为参考。如果您忘记了,也可以稍后在解决方案资源管理器 window.

中添加这些引用

在解决方案资源管理器中,在测试项目的快捷菜单上,选择“属性”。项目属性 window 打开。

选择配置属性、链接器、输入、附加依赖项。

选择“编辑”,然后添加 .obj 或 .lib 文件的名称。不要使用完整路径名。

对我来说,只有 .obj 文件。我在 Intermediates 文件夹中找到了它们,其中有多个版本,每个版本对应解决方案平台(x86 或 x64)和解决方案配置(调试或发布)的组合。如果您有很多 .obj(或 .lib)文件,我发现打开终端和 运行 ls(或 dir)获取文件名、编辑 .log、.txt 和 .pdb 很方便我不需要的文件名,然后将 .obj 文件名列表复制粘贴到 Visual Studio。为了方便编辑,请注意,您可以单击“附加依赖项”输入字段右侧的下拉箭头,然后单击“编辑”。

选择配置属性、链接器、常规、附加库目录。

选择编辑,并添加.obj 或.lib 文件的目录路径。该路径通常位于被测项目的构建文件夹中。

对我来说,我只有 .obj 文件。我在 Intermediates 文件夹中找到了它们,其中有多个版本,每个版本对应解决方案平台(x86 或 x64)和解决方案配置(调试或发布)的组合。为所有 4 种组合设置此路径的便捷宏是:$(SolutionDir)bin\$(PlatformTarget)\$(IntermediateOutputPath)Intermediates。您可能需要取出 bin\ 部分,因为我还看到输出文件夹直接设置在解决方案目录中,而不是在单独的二进制文件夹中。

选择配置属性,VC++ 目录,包含目录。

选择编辑,然后添加被测项目的header目录。

对于这个目录,可以直接指向属于被测项目的文件夹。无需将 header 文件复制到测试项目。如果此目录包含的不仅仅是 header 也没有关系。例如,我的源文件夹同时包含 .h 文件和 .cpp 文件。

完成这些步骤后,我可以通过简单地编写以下代码将 header 文件包含在我的测试代码中:

#include "SomeHeaderName.h"

因此,无需指定 header 文件所在的文件夹。

确保清理并重建整个解决方案。然后,您的测试应该能够访问您正在测试的项目的功能。

我认为选择的答案不正确。测试通常应该在他们的环境中 运行;因此,他们不应访问实现 (.cpp)


当您在 Visual Studio (VS 2017) 上创建单独的测试项目时,您需要创建对要测试的项目的引用(右键单击测试项目 -> 添加 -> 引用 -> 勾选项目): Add a reference

如果您看到一些链接器错误,请从单元测试项目中右键单击:项目->链接器->输入->附加依赖项->编辑 然后将路径添加到您的 .obj 文件。 您可以尝试“$(SolutionDir)ConsoleApplication1\$(IntDir)*.obj”,其中 ConsoleApplication1 是目标项目名称。

Path to .obj

最初,我只想对 Cornelis 的 post 发表评论,但我不能。