【问题标题】:Workaround for XCTest failures due to dispatch_once?由于 dispatch_once 导致 XCTest 失败的解决方法?
【发布时间】:2014-04-26 05:40:09
【问题描述】:

如果多个测试需要运行 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 之外,还有其他解决方案吗?

【问题讨论】:

    标签: objective-c xcode xctest


    【解决方案1】:

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

    【讨论】:

    • 谢谢。将保留附加到 arrayWithObjects 固定的东西。
    猜你喜欢
    • 2011-03-31
    • 1970-01-01
    • 1970-01-01
    • 2014-09-05
    • 1970-01-01
    • 2022-06-22
    • 2010-09-20
    • 2021-01-18
    • 2021-11-10
    相关资源
    最近更新 更多