Foo类在MyApp和MyAppTestCase中实现.将使用两者之一.哪一个未定义

nac*_*o4d 63 macos xcode cocoa objective-c

最近我开始单元测试我的应用程序.这个项目(在Xcode4中)是在没有单元测试包的情况下创建的,所以我不得不进行设置.我已经按照这里的步骤进行了操作:http://cocoawithlove.com/2009/12/sample-mac-application-with-complete.html 并且它适用于简单的类,但现在我正在尝试测试依赖的类在另一个和另一个,等等

首先我收到了一个链接器错误,所以我将*.m文件添加到测试用例目标但现在我收到了一个警告,我正在尝试测试的每个类:

Foo类在MyApp和MyAppTestCase中实现.将使用两者之一.哪一个未定义.

我想知道为什么会这样?我怎么解决这个问题?也许我在设置单元测试目标时错过了什么?

编辑 - 解决方案

  • 正确设置"Bundle Loader" $(BUILT_PRODUCTS_DIR)/AppName.app/AppName

  • 将"默认隐藏的符号" 设置为NO(在目标应用程序的" 构建设置"中).这是链接器错误的来源,因为它默认为YES!我一直在努力奋斗这么久!

来源:使用XCode 4进行单元测试的链接错误?

jus*_*tin 43

Foo类在MyApp和MyAppTestCase中实现.将使用两者之一.哪一个未定义.

我想知道为什么会这样?

因为两个图像(应用程序和单元测试包)都定义了类的实现.该类被动态加载到objc运行时.objc运行时使用平面命名空间.这是如何工作的:

  • 从其依赖项开始加载二进制文件
  • 在加载每个二进制文件时,objc类向objc运行时注册
  • 如果加载了两次具有特定名称的类,则行为未定义.可以将一个类(具有相同名称)的实现加载到objc运行时中.

这里的典型问题是您将返回一个实现 - 当类型冲突时(当类不来自同一源文件时),您的应用程序可能会崩溃.

您通常可以通过重命名类或在一个图像中导出类来避免这种情况.重命名该课程显然不适用于您的情况.你有一个文件Foo.m正在被两个图像编译,导出和加载,当它应该在一个文件中时.

这应该被解释为重复的符号链接器错误.即使实现是相同的源文件(并且实现是相同的) - 这是一个必须修复的问题.

我怎么解决这个问题?

如果Foo.m是应用程序的类,则必须Foo.m从单元测试中删除(不编译和链接).如果它是单元测试的一部分,那么不要编译并将其链接到单元测试目标.

然后,按照帖子中的说明将您的单元测试链接/加载到应用程序.它位于帖子的这个一般区域:其中"WhereIsMyMac"是您单元测试的应用程序的名称.这将使测试目标链接到应用程序(因此编译时不会出现链接器错误).重要的是,您的测试文件是在单元测试目标中编译的(仅限),您的应用程序的类将被编译并链接到应用程序中.你不能只是添加它们 - 它们动态链接和加载.

也许我在设置单元测试目标时错过了什么?

从你链接的文章:

注意:测试目标是一个单独的目标.这意味着您需要注意目标成员资格.应将所有应用程序源文件仅添加到应用程序目标.测试代码文件只应添加到测试目标中.

你错了的部分可能是单元测试包的链接和加载阶段.


Ric*_*ard 17

如果您正在使用Cocoapods,则您的podfile仅需要主要目标部分中的依赖项,而不是测试目标.如果确实为测试目标添加了重复的依赖项,则会收到OP的错误消息.

target 'MyProject' do
pod 'Parse'

end

target 'MyProjectTests' do

end

target 'MyProjectUITests' do

end
Run Code Online (Sandbox Code Playgroud)


Ste*_*HHH 12

对我来说,我需要做的只是取消选中使Foo类成为单元测试目标成员的复选框.它不应该是两个目标的成员,并且应该如下所示:

目标会员

如果您看不到图像,它是Xcode"目标成员资格"窗格的屏幕截图.有两个目标:一个带有"A"应用程序图标和测试名称.另一个是单元测试目标,并有一个单元测试图标:

Target Membership
[X] Foo
[ ] FooTests
Run Code Online (Sandbox Code Playgroud)