Xcode单元测试 - 仅为设备构建时链接错误

ede*_*y05 14 xcode unit-testing ios

我的应用程序单元在模拟器中运行时测试构建和测试,但在构建和测试设备时失败并出现链接器错误.

在我的应用程序目标上,我设置了以下构建设置:

DEPLOYMENT_POSTPROCESSING = NO
GCC_SYMBOLS_PRIVATE_EXTERN = NO
Run Code Online (Sandbox Code Playgroud)

在我的单元测试中,我设置了以下构建设置:

BUNDLE_LOADER = $(BUILT_PRODUCTS_DIR)/<app name>.app/<app>
TEST_HOST = $(BUNDLE_LOADER)
Run Code Online (Sandbox Code Playgroud)

链接器错误是:

Undefined symbols for architecture armv7s:
"_<An NSString * const>", referenced from:
      -[UnitTestClassA setUp] in UnitTestClassA.o
"_<Another NSString * const>", referenced from:
      -[UnitTestClassB helperMethod:] in UnitTestClassB.o
      -[UnitTestClassB anotherHelperMethod:] in UnitTestClassB.o
ld: symbol(s) not found for architecture armv7s
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Run Code Online (Sandbox Code Playgroud)

...我在Xcode的首选项中打开"继续构建错误后继续",但是我没有收到大量关于NSString*const的链接器错误.如果我做错了什么,那么由于我在整个生产代码中使用字符串常量,因此我会得到比我少数人更多的链接错误.

我正在创建我的字符串常量:

.h文件......

extern NSString * const ReallyGoodString;
Run Code Online (Sandbox Code Playgroud)

.m文件...

NSString * const ReallyGoodString = @"This string is great!";
Run Code Online (Sandbox Code Playgroud)

... .m文件是生产代码,也是我的应用程序目标的一部分,因此我不必将其链接到单元测试包中.

那么,这里发生了什么?为什么这在模拟器中工作得很好而不在设备上呢?

我已经向Github发布了一个示例项目来说明问题.您可以在示例项目中看到此问题不一致:某些符号链接很好,其他符号则不然.

rob*_*off 27

当链接器创建Linker-Error可执行文件时,它会丢弃,FHKViewControllerThisSymbolWontLink因为可执行文件中没有任何内容使用它.链接器不知道它应该保持单元测试包(在运行时动态加载)使用的符号.

您可以告诉链接器不要通过使用used属性标记它来剥离未使用的符号,如下所示:

NSString * const FHKViewControllerThisSymbolWontLink __attribute__((used)) = @"name";
Run Code Online (Sandbox Code Playgroud)

您需要为您定义的每个符号执行此操作,该符号不是主可执行文件使用但由测试套件使用.


Bla*_*ers 12

这很可能是因为您的测试套件正在使用的主要应用程序未使用的符号和启用了死代码剥离功能.您可以在每个配置的基础上禁用死代码剥离选项.我修复了一个类似的问题,通过将选项翻转到No for Debug builds ,使测试能够在我的设备上运行.