5

I have a series of unit tests written using XCTest framework. These were originally created on iOS7, then executed in xCode6 on iOS8 device. The tests are executing in sequence, but then I get EXC_BAD_ACCESS (code= 1, address 0xc) for the following code block. This happens when tests are executed using the "Test" command from xcode.

If I execute this test individually from the test left panel, it passes or fails normally.

Here's what I think I'm doing:

  • Set up expectation
  • Get datasource (old one is returned immediately)
  • Asynchronously update datasource from network resource.
  • The test case gets notified of the delegate callback and fulfills expectation

How can I make sure that I can execute all of my unit tests without exceptions?

//unit test

-(void)testNetworkDataSourceUpdate
{
    self.expectation = [self expectationWithDescription:@"Getting network datasource"];

    DataSource* dataSource = [DataSourceProvider datasourceWithRefreshDelegate:self];
    XCTAssertNotNil(dataSource, @"Should have datasource immediately available");


    //Bad access here
    [self waitForExpectationsWithTimeout:10.0 handler:^(NSError *error) {

    }];

}

//callback

-(void)refreshDatasource:(NSMutableArray*)datasource
{

   [self.expectation fulfill];
}
Alex Stone
  • 46,408
  • 55
  • 231
  • 407

1 Answers1

0

I had the same problem which led to a crash on every block call.

The error was caused by the main application which was running in the background. You can prevent this my adding your own AppDelegate for your test target, which does not start the usual app flow. Therefore, remove the old AppDelegate from the test target, create a new one and add it to your test target.

Then you have to change your main.m file to setup the right app delegate on the app start:

int main(int argc, char *argv[]) {
    @autoreleasepool {
        int returnValue;
        BOOL inTests = NSClassFromString(@"XCTest") != nil;

        if (inTests) {
            //use a special empty delegate when we are inside the tests
            returnValue = UIApplicationMain(argc, argv, nil, @"AppDelegateTest");
        } else {
            //use the normal delegate
            returnValue = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
        }

        return returnValue;
    } }
Patrick Haaser
  • 353
  • 1
  • 3
  • 10