Foo 类在 MyApp 和 MyAppTestCase 中实现.将使用两者之一.哪个是未定义的 [英] Class Foo is implemented in both MyApp and MyAppTestCase. One of the two will be used. Which one is undefined

查看:25
本文介绍了Foo 类在 MyApp 和 MyAppTestCase 中实现.将使用两者之一.哪个是未定义的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近我开始对我的应用程序进行单元测试.这个项目(在 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 进行单元测试时链接错误?

<块引用>

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

我想知道这是为什么?

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

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

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

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

<块引用>

我该如何解决这个问题?

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

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

<块引用>

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

来自您链接的文章:

<块引用><块引用>

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

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

Recently I started Unit testing my application. This project (in Xcode4) was created without a unit test bundle so I had to set it up. I have followed the steps from here: http://cocoawithlove.com/2009/12/sample-mac-application-with-complete.html And It was working well for simple classes but now I am trying to test a class that depends on another and that on another, etc.

First I got a linker error so I added *.m files to the test case target but now I get a warning for every class I am trying to test:

Class Foo is implemented in both MyApp and MyAppTestCase. One of the two will be used. Which one is undefined.

I wonder why is that? How can I solve this? Maybe I missed something when setting the unit test target?

Edit - The Solution

  • Set "Bundle Loader" correctly to $(BUILT_PRODUCTS_DIR)/AppName.app/AppName

  • Set "Symbols Hidden by Default" to NO (in Build Settings of the target application). This is where the linker errors come from because it is YES by default!. I've been struggling with this for so long!.

Source: Linking error for unit testing with XCode 4?

解决方案

Class Foo is implemented in both MyApp and MyAppTestCase. One of the two will be used. Which one is undefined.

I wonder why is that?

because both images (the app and the unit test bundle) define the implementation of the class. the class is dynamically loaded into the objc runtime. the objc runtime uses a flat namespace. how this works:

  • the binary is loaded, starting with its dependencies
  • as each binary is loaded, the objc classes register with the objc runtime
  • if a class with a specific name is loaded twice, the behaviour is undefined. one implementation of a class (with identical names) can be loaded into the objc runtime.

the typical problem here is that you will be returned one implementation - your app will likely crash when the type conflicts (when the class does not come from the same source file).

you typically avoid this by either renaming a class, or export the class in one image. renaming the class obviously does not apply to your case. you have one file Foo.m which is being compiled, exported, and loaded by two images when it should be in one.

this should be interpreted by you as a duplicate symbol linker error. even though the implementation is the same source file (and the implementation is the same) - this a problem that you must fix.

How can I solve this?

if Foo.m is a class of the app, you have to remove (do not compile and link) Foo.m from the unit test. if it's part of the unit test, then do not compile and link it into the unit test target.

then, follow the instructions in the post for linking/loading your unit test to the app. it's in this general area of the post: where "WhereIsMyMac" is the name of the application you're unit testing. This will let the testing target link against the application (so you don't get linker errors when compiling). the important part is that your test files are compiled in the unit test target (only), and your app's classes are compiled and linked into the app. you can't just add them - they link and load dynamically.

Maybe I missed something when setting the unit test target?

From the article you linked:

Note: The testing target is a separate target. This means that you need to be careful of target membership. All application source files should be added to the application target only. Test code files should be added to the testing target only.

the part that you got wrong is probably the link and load phases of the unit test bundle.

这篇关于Foo 类在 MyApp 和 MyAppTestCase 中实现.将使用两者之一.哪个是未定义的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆