سؤال

If multiple tests require running a dispatch_once() then only one test passes.

Here is an example of the issue (non-ARC code):

#import <XCTest/XCTest.h>

@interface TestBrokenDispatchOnce : XCTestCase

@end

@implementation TestBrokenDispatchOnce

+(NSArray*) get {
    static NSArray* _get;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _get=[NSArray arrayWithObjects:@(1),@(2),nil];
    });

    return _get;
}

- (void)testOne {
    for(NSNumber* n in [[self class] get]) {
        NSLog(@"%@",n);
    }

    XCTAssertTrue(YES, @"pass");    
}

- (void)testTwo {
    // will die here with access exception
    for(NSNumber* n in [[self class] get]) {
        NSLog(@"%@",n);
    }

    XCTAssertTrue(YES, @"pass");
}

@end

Each test case run separately will pass, but the second will fail if both are run.

The actual problem I am seeing is in testing against a (non-ARC library) which uses dispatch_once to lazy-initialise an array, but the failure is the same as this minimal example. I am guessing that the XCTest framework is releasing some memory pool so the NSArray is deallocated, but the statics are left initialised.

Is there a solution for this, other than to reset the onceToken in the tests?

هل كانت مفيدة؟

المحلول

The test is exposing a memory management issue in the get method. Since arrayWithObjects: returns an autoreleased object, under MRC the array _get points to is released the next time the autorelease pool is popped. To fix this the array needs to be retained, either by allocating it using initWithObjects: or sending a retain message to the object returned by arrayWithObjects:.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top