Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linker Error: iPhone Unit Test Bundle referencing App classes

Starting with an app already in development, I have carried out the instructions in the iPhone Development Guide – Unit Testing Applications

I can successfully include and use my App's classes in Application-style tests that run on the device, and output their results to the console.

If I add the following line of code:

STAssertTrue([viewController isKindOfClass:[LoginViewController class]], @"Top view controller is not LoginViewController");

The following build error is generated:

Undefined symbols:
  "_OBJC_CLASS_$_LoginViewController", referenced from:
      __objc_classrefs__DATA@0 in LoginViewTest.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

I can provide more configuration information for the project and the Testing target, but the setup works file without the [LoginViewController class] line in the test source.

Without that line, I can reference the class, use it's properties and send it messages successfully.

Is there a linking build setting, or bundle loading option that is required when attempting to use an App class in this fashion? Or should I find another type of test to confirm that the class of an object is the expected one?

like image 420
ohhorob Avatar asked Nov 11 '09 05:11

ohhorob


1 Answers

I have found an answer, but I think there must be a "better" way?

In the build configuration for the Unit Tests bundle, you can specify the Bundle Loader (BUNDLE_LOADER) setting that points to your "host" App.

${TARGET_BUILD_DIR}/AppName.app/AppName

The Unit Tests bundle is being built as a dependency of your App's unit testing target (say, AppName Testing), and as a result I haven't been able to resolve the App executable any better than the above.

The net result is a working unit test injected into the Testing target without any linker errors. The tests run and access the classes as expected.

EDIT: Bundle Loader – Target Configuration

It's important to configure the target that is "hosting" the testing bundle to not hide it's symbols.

GCC_SYMBOLS_PRIVATE_EXTERN = NO

a.k.a. "Symbols hidden by default". From the documentation:

When enabled, all symbols are declared 'private extern' unless explicitly marked to be exported using '__attribute__((visibility("default")))' in code. If not enabled, all symbols are exported unless explicitly marked as 'private extern'.

For more information, see http://developer.apple.com/documentation/DeveloperTools/Conceptual/CppRuntimeEnv/Articles/SymbolVisibility.html.

like image 57
ohhorob Avatar answered Sep 30 '22 14:09

ohhorob