带有.mm测试文件的OCMock 3.0.2链接器错误

时间:2014-07-24 08:25:07

标签: c++ xcode linker-errors ocmock

我正在使用OCMock 3.0.2,我通过cocoapods安装了我的测试目标:

platform :ios, '7.0'
xcodeproj 'myProject.xcodeproj'

target :myTestTarget do
  pod 'OCMock', '~> 3.0.2'
end

link_with "myTestTarget"

在我的测试文件(myTest.mm)中,我已经包含了OCMock,并希望尝试新的就地验证策略,如下所示:

- (void) test_myTest
{
    MyObject *obj = [MyObject new];
    id robotMock = OCMPartialMock(obj);

    [obj testMethod];

    // some asserts
    OCMVerify([obj _internalMethodToBeCalled]);
}

到目前为止似乎很正常。但是,当我尝试运行此特定测试用例时,我收到链接器错误:

Undefined symbols for architecture i386:
  "OCMMakeLocation(objc_object*, char const*, int)", referenced from:
      -[MyTests test_myTest] in MyTests.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

我确认已正确引入OCMock并且也引用了OCMLocation.h / m文件。我看到OCMMakeLocation似乎是一个外部函数,但.m文件作为我的pods构建目标中的依赖项目存在,但不知何故它没有被链接。我必须让我的测试成为.mm,因为我包含了一些c ++文件。为什么这会成为OCMock的问题?

2 个答案:

答案 0 :(得分:7)

OCMMakeLocation声明如下

OCMLocation.h:

extern OCMLocation *OCMMakeLocation(id testCase, const char *file, int line);

OCMLocation.m:

OCMLocation *OCMMakeLocation(id testCase, const char *fileCString, int line)
{
    return [OCMLocation locationWithTestCase:testCase file:[NSString stringWithUTF8String:fileCString] line:line];
}

这是在Objective-C界面之外定义的直接C函数。我不太了解编译器实际上在做什么(也许其他人可以更好地解释它),但据我所知,这是正在发生的事情:你的测试文件是一个Objective-C ++文件,所以它已经得到了符合C ++链接,它命名为mangling(see this about name mangling)。但是,OCMLocation被编译为Objective-C文件,因此它获得C链接,而不是C ++链接,因此没有名称重整。因为你的测试符合C ++链接,所以它会引入OCMock.h并假设它也是一个C ++头,所以它假定编译它的源的结果是相同的,它不会是。

长话短说,要解决此问题,您需要做的就是告诉编译器OCMock.h是测试文件中的C头:

#ifdef __cplusplus
extern "C" {
#endif
#import <OCMock/OCMock.h>
#ifdef __cplusplus
}
#endif

答案 1 :(得分:0)

看起来你正在从源代码构建OCMock,你只是为x86_64(64位)构建它,然后尝试在i386(32位)的项目中使用二进制文件。使用下载页面中提供的预构建二进制文件可以解决您的问题,因为这些二进制文件 fat <​​/ em>,它们包含i386和x86_64。

可能是Cocoapods正在尝试进行Debug构建,其中“only active args”设置为true。我不太了解Cocoapods如何强制它进行Release构建,这应该会创建胖二进制文件。