如果多个测试需要运行dispatch_once(),那么只有一个测试通过。
以下是问题的示例(非ARC代码):
#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
每个单独运行的测试用例都会通过,但如果两个测试用例都运行则第二个将失败。
我看到的实际问题是针对使用dispatch_once来延迟初始化数组的(非ARC库)进行测试,但失败与此最小示例相同。我猜测XCTest框架正在释放一些内存池,因此NSArray被释放,但是静态的初始化。
除了在测试中重置onceToken之外,还有解决方法吗?
答案 0 :(得分:2)
测试是在get
方法中暴露内存管理问题。由于arrayWithObjects:
返回一个自动释放的对象,因此在下一次弹出自动释放池时,在MRC下指向的数组_get
将被释放。要解决这个问题,需要保留数组,方法是使用initWithObjects:
分配数组,或者向arrayWithObjects:
返回的对象发送保留消息。