objective-c - 由于dispatch_once导致XCTest失败的解决方法?

标签 objective-c xcode xctest

如果多个测试需要运行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

单独运行的每个测试用例都会通过,但如果同时运行,第二个测试用例将会失败。

我看到的实际问题是针对(非 ARC 库)进行测试,该库使用dispatch_once 延迟初始化数组,但失败与这个最小示例相同。我猜测 XCTest 框架正在释放一些内存池,因此 NSArray 被释放,但静态变量仍处于初始化状态。

除了在测试中重置onceToken之外,还有其他解决方案吗?

最佳答案

该测试暴露了 get 中的内存管理问题方法。自 arrayWithObjects:返回一个自动释放的对象,在 MRC 下数组 _get指向的值会在下次弹出自动释放池时被释放。要解决此问题,需要保留数组,方法是使用 initWithObjects: 分配它。或向 arrayWithObjects: 返回的对象发送一条保留消息.

关于objective-c - 由于dispatch_once导致XCTest失败的解决方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23307118/

相关文章:

ios - 如何使用 XCTest UI 测试区分 iOS 13 中的标题和静态文本

ios - @available 属性不适用于 XCTest 类或方法

ios - 无法在真实设备上更新 plist 文件

xcode - Three20 v1.1和Xcode 4

c++ - Apple LLVM 4.1 的 STD 链接器错误

ios - Facebook Unity SDK,损坏的 iOS 后处理器

ios - Xcode 6 中的 XCTest 和异步测试

iphone - SQLite查询使用SQLite的“like”子句查找相似的单词

ios - 我如何使用 NSJSONSerialization 与特殊字符,如 "ñ"?

objective-c - @implementation 附近的委托(delegate)是做什么的?