Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
475 views
in Technique[技术] by (71.8m points)

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

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...