Linker Error: iPhone Unit Test Bundle referencing

2019-02-06 17:56发布

问题:

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?

回答1:

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.



回答2:

I just answered this over here:

iPhone unit testing: Symbols not found when calling custom code

I suppose one of these should be closed as a duplicate? I'm not reputable enough to do so...


I also followed Apple's iPhone Unit Testing Applications document and saw a linking error similar to the one described in the question when trying to unit test one of my classes.

Looks like any class referenced in your unit test class and so being run from your test target also needs to be added to that test target. To do this, you would right click your RootViewController class and click 'Get Info' (Cmd-i shortcut). On the targets pane, make sure your unit test target (e.g. 'LogicTests', if you've followed the naming in that document) is checked.

Now that class will be compiled with your tests and should be available to your unit test. To double check, expand the 'Targets/LogicTests/Compile Resources' node in the 'Groups & Files' browser on the left. This lists all the class files available when building the target and should now include your unit test class together with your class under test.

(Note that you'll need to similarly select all appropriate targets when you create a new application or test class - on the same page of the 'New File...' window when you name the file).

(I'm using XCode 3.2.3 & OS 4.0, by the way).