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:
.
Workaround for XCTest failures due to dispatch_once?
-
09-07-2023 - |
Вопрос
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?
Решение
Не связан с StackOverflow