iPhone unit testing: Symbols not found when callin

2020-03-08 06:26发布

问题:

I'm trying to set up unit testing for my iPhone application. I followed the Apple Unit Testing documentation through and that woked fine, but as soon as I added another class in to that test, I get the following error:

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

The application itself is a basic navigation app with Core data for data storage.

The unit test is as follows:

#import <SenTestingKit/SenTestingKit.h>
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>

#import "HSStabilityAppAppDelegate.h"
#import "RootViewController.h"
@interface AppDelegateTests : SenTestCase {
 HSStabilityAppAppDelegate *appDelegate;
}
@end


@implementation AppDelegateTests
// all code under test must be linked into the Unit Test bundle


#pragma mark -
#pragma mark Set up and tearDown

#if APPLICATION_TESTS
- (void) setUp {
 appDelegate = (HSStabilityAppAppDelegate *)[[UIApplication sharedApplication] delegate];
 STAssertNotNil(appDelegate, @"Cannot find the application delegate.");
}

- (void) tearDown {
 [appDelegate release];
}

#else

#endif


#pragma mark -
#pragma mark Tests

#if APPLICATION_TESTS

- (void) testRootViewIsOnTop {
 id topViewControllerClass = [[appDelegate.navigationController topViewController] class];
 id rootViewControllerClass = [RootViewController class];
 STAssertEquals(topViewControllerClass, rootViewControllerClass, @"Root view controller was not the top class");
}

#endif

@end

If I comment out the id rootViewControllerClass line then the program links correctly. Also, this only occurs when building against the device target, I don't have any problems if building against the simulator (probably given that application tests don't work on the simulator).

Can anyone help solve this basic and very infuriating problem?

回答1:

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).



回答2:

I believe I've found the answer. The problem is that whilst the compiler can see the definitions, it isn't looking in the right place when linking them up and so throws those errors. Therefore, if we move the class name resolution to runtime, we can get round all this.

Instead of:NSManagedObject use: NSClassFromString("@NSManagedObject")

This goes for pretty much all classes defined within.

If anyone can tell me how to make it work at compile time I'd still be very grateful.