使用 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 发表评论,但我不能。
我想用 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 发表评论,但我不能。