首页 > 解决方案 > 使用 Catch2 时未解决的外部符号错误

问题描述

我正在尝试在 Visual Studio 中进行 Catch2 单元测试。我创建了一个小测试项目来练习。当我尝试编译这个测试项目时,我得到一个链接器错误。我现在正在尝试诊断此链接器错误,但Catch2.hpp头文件包含数千行代码。我希望更熟悉 Catch2 或单元测试的人可以诊断出问题所在。

我将描述我创建这个项目的过程。我在新解决方案中创建了一个新项目。我有 4 个文件,都在同一个目录中,如下所示。

我要测试的课程:

//a.h

#pragma once

class A {
    friend int A_Tester_Func1(A a);
public:
    A(int num) : my_num_(num) {
    }
private:
    int my_num_;
};

考试:

//atester.cpp

#pragma once

#include "catch.hpp"
#include "a.h"

int A_Tester_Func1(A a) {
    return a.my_num_;
}

TEST_CASE("a contains a positive integer", "[a]") {
    //...
    A a(3);
    REQUIRE(A_Tester_Func1(a) == 3);

}

运行测试的主要函数:

//tester.cpp

#define CATCH_CONFIG_MAIN
#include "catch.hpp" // this should create the main function

Catch2 测试框架:

// catch.hpp

/*
 *  Catch v2.13.2
 *  Generated: 2020-10-07 11:32:53.302017
*/

//~17-18k lines of code that from Catch2

#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED

当我尝试使用本地 Windows 调试器按钮在 Visual Studio 中编译此代码时,我收到一堆未解决的外部符号链接器错误。我相信我在某处读到 Catch2 是“部分编译的”。这可能与它有关,但我不知道。遵循本指南(StackOverflow:Visual Studio 中使用 Catch2 进行单元测试的最佳实践)对我有用,但我试图理解为什么上面的小示例没有成功链接。

为了完整起见,我在下面包含了链接器错误,尽管我认为它们可能不是问题所必需的。

1>atester.obj : error LNK2019: unresolved external symbol "public: __thiscall Catch::StringRef::StringRef(char const *)" (??0StringRef@Catch@@QAE@PBD@Z) referenced in function "public: class Catch::BinaryExpr<int const &,int const &> const __thiscall Catch::ExprLhs<int const &>::operator==<int>(int const &)" (??$?8H@?$ExprLhs@ABH@Catch@@QAE?BV?$BinaryExpr@ABHABH@1@ABH@Z)
1>atester.obj : error LNK2019: unresolved external symbol "struct Catch::ITestInvoker * __cdecl Catch::makeTestInvoker(void (__cdecl*)(void))" (?makeTestInvoker@Catch@@YAPAUITestInvoker@1@P6AXXZ@Z) referenced in function "void __cdecl `anonymous namespace'::`dynamic initializer for 'autoRegistrar1''(void)" (??__EautoRegistrar1@?A0xf9ca9c7d@@YAXXZ)
1>atester.obj : error LNK2019: unresolved external symbol "public: __thiscall Catch::NameAndTags::NameAndTags(class Catch::StringRef const &,class Catch::StringRef const &)" (??0NameAndTags@Catch@@QAE@ABVStringRef@1@0@Z) referenced in function "void __cdecl `anonymous namespace'::`dynamic initializer for 'autoRegistrar1''(void)" (??__EautoRegistrar1@?A0xf9ca9c7d@@YAXXZ)
1>atester.obj : error LNK2019: unresolved external symbol "public: __thiscall Catch::AutoReg::AutoReg(struct Catch::ITestInvoker *,struct Catch::SourceLineInfo const &,class Catch::StringRef const &,struct Catch::NameAndTags const &)" (??0AutoReg@Catch@@QAE@PAUITestInvoker@1@ABUSourceLineInfo@1@ABVStringRef@1@ABUNameAndTags@1@@Z) referenced in function "void __cdecl `anonymous namespace'::`dynamic initializer for 'autoRegistrar1''(void)" (??__EautoRegistrar1@?A0xf9ca9c7d@@YAXXZ)
1>atester.obj : error LNK2019: unresolved external symbol "public: virtual __thiscall Catch::AutoReg::~AutoReg(void)" (??1AutoReg@Catch@@UAE@XZ) referenced in function "void __cdecl `anonymous namespace'::`dynamic atexit destructor for 'autoRegistrar1''(void)" (??__FautoRegistrar1@?A0xf9ca9c7d@@YAXXZ)
1>atester.obj : error LNK2019: unresolved external symbol "public: static class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl Catch::StringMaker<int,void>::convert(int)" (?convert@?$StringMaker@HX@Catch@@SA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@Z) referenced in function "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl Catch::Detail::stringify<int>(int const &)" (??$stringify@H@Detail@Catch@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABH@Z)
1>atester.obj : error LNK2019: unresolved external symbol "public: virtual __thiscall Catch::ITransientExpression::~ITransientExpression(void)" (??1ITransientExpression@Catch@@UAE@XZ) referenced in function "public: virtual __thiscall Catch::BinaryExpr<int const &,int const &>::~BinaryExpr<int const &,int const &>(void)" (??1?$BinaryExpr@ABHABH@Catch@@UAE@XZ)
1>atester.obj : error LNK2019: unresolved external symbol "void __cdecl Catch::formatReconstructedExpression(class std::basic_ostream<char,struct std::char_traits<char> > &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class Catch::StringRef,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?formatReconstructedExpression@Catch@@YAXAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@3@VStringRef@1@1@Z) referenced in function "private: virtual void __thiscall Catch::BinaryExpr<int const &,int const &>::streamReconstructedExpression(class std::basic_ostream<char,struct std::char_traits<char> > &)const " (?streamReconstructedExpression@?$BinaryExpr@ABHABH@Catch@@EBEXAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@@Z)
1>atester.obj : error LNK2019: unresolved external symbol "public: __thiscall Catch::AssertionHandler::AssertionHandler(class Catch::StringRef const &,struct Catch::SourceLineInfo const &,class Catch::StringRef,enum Catch::ResultDisposition::Flags)" (??0AssertionHandler@Catch@@QAE@ABVStringRef@1@ABUSourceLineInfo@1@V21@W4Flags@ResultDisposition@1@@Z) referenced in function "void __cdecl ____C_A_T_C_H____T_E_S_T____0(void)" (?____C_A_T_C_H____T_E_S_T____0@@YAXXZ)
1>atester.obj : error LNK2019: unresolved external symbol "public: void __thiscall Catch::AssertionHandler::handleExpr(struct Catch::ITransientExpression const &)" (?handleExpr@AssertionHandler@Catch@@QAEXABUITransientExpression@2@@Z) referenced in function "void __cdecl ____C_A_T_C_H____T_E_S_T____0(void)" (?____C_A_T_C_H____T_E_S_T____0@@YAXXZ)
1>atester.obj : error LNK2019: unresolved external symbol "public: void __thiscall Catch::AssertionHandler::handleUnexpectedInflightException(void)" (?handleUnexpectedInflightException@AssertionHandler@Catch@@QAEXXZ) referenced in function __catch$?____C_A_T_C_H____T_E_S_T____0@@YAXXZ$0
1>atester.obj : error LNK2019: unresolved external symbol "public: void __thiscall Catch::AssertionHandler::complete(void)" (?complete@AssertionHandler@Catch@@QAEXXZ) referenced in function __catch$?____C_A_T_C_H____T_E_S_T____0@@YAXXZ$0
1>MSVCRTD.lib(exe_main.obj) : error LNK2019: unresolved external symbol _main referenced in function "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ)

是什么导致了这些错误?如何catch.hpp在与源文件保存在同一个项目中的同时修复这些错误?

标签: c++visual-studiounit-testinglinker-errorscatch2

解决方案


在 .cpp 文件中,添加以下内容以使项目成为 Catch2 测试运行器:

#define CATCH_CONFIG_RUNNER
#include "catch.hpp"

在自己提供 main()中阅读更多信息


推荐阅读