XCTestExpectation:如何避免在等待上下文结束后调用fulfill方法?

2024-04-28

我正在使用 Xcode 6 的新异步测试功能。当异步任务在超时之前结束时,一切正常。但如果任务花费的时间超过超时时间,事情就会变得更加复杂。

这是我进行测试的方式:

@interface AsyncTestCase : XCTestCase @end

@implementation AsyncTestCase

// The asynchronous task would obviously be more complex in a real world scenario.
- (void) startAsynchronousTaskWithDuration:(NSTimeInterval)duration completionHandler:(void (^)(id result, NSError *error))completionHandler
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        completionHandler([NSObject new], nil);
    });
}

- (void) test1TaskLongerThanTimeout
{
    XCTestExpectation *expectation = [self expectationWithDescription:@"Test 1: task longer than timeout"];
    [self startAsynchronousTaskWithDuration:4 completionHandler:^(id result, NSError *error) {
        XCTAssertNotNil(result);
        XCTAssertNil(error);
        [expectation fulfill];
    }];
    [self waitForExpectationsWithTimeout:2 handler:nil];
}

- (void) test2TaskShorterThanTimeout
{
    XCTestExpectation *expectation = [self expectationWithDescription:@"Test 2: task shorter than timeout"];
    [self startAsynchronousTaskWithDuration:5 completionHandler:^(id result, NSError *error) {
        XCTAssertNotNil(result);
        XCTAssertNil(error);
        [expectation fulfill];
    }];
    [self waitForExpectationsWithTimeout:10 handler:nil];
}

@end

不幸的是,打电话给fulfill超时到期后的方法会使测试套件崩溃并出现以下错误:

API 违规 - 等待上下文结束后调用 -[XCTestExpectation fill]。

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'API violation - called -[XCTestExpectation fulfill] after the wait context has ended.'
*** First throw call stack:
(
  0   CoreFoundation   0x000000010c3a6f35 __exceptionPreprocess + 165
  1   libobjc.A.dylib  0x000000010a760bb7 objc_exception_throw + 45
  2   CoreFoundation   0x000000010c3a6d9a +[NSException raise:format:arguments:] + 106
  3   Foundation       0x000000010a37d5df -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 195
  4   XCTest           0x0000000115c48ee1 -[XCTestExpectation fulfill] + 264
  ...
)
libc++abi.dylib: terminating with uncaught exception of type NSException

当然,我可以在调用之前检查测试是否完成fulfill像这样的方法:

- (void) test1TaskLongerThanTimeout
{
    XCTestExpectation *expectation = [self expectationWithDescription:@"Test 1: task longer than timeout"];

    __block BOOL testIsFinished = NO;
    [self startAsynchronousTaskWithDuration:4 completionHandler:^(id result, NSError *error) {
        if (testIsFinished) {
            return;
        }
        XCTAssertNotNil(result);
        XCTAssertNil(error);
        [expectation fulfill];
    }];

    [self waitForExpectationsWithTimeout:2 handler:^(NSError *error) {
        testIsFinished = YES;
    }];
}

但这似乎过于复杂,使得测试更难阅读。我错过了什么吗?有没有更简单的方法来解决这个问题?


是的,有一种更简单的方法可以避免此 API 违规问题:只需将您的期望变量声明为__weak。尽管没有明确记录,但当超时到期时,期望将被释放。因此,如果任务花费的时间超过超时时间,则调用任务完成处理程序时期望变量将为 nil。就这样fulfill方法将在 nil 上调用,不执行任何操作。

- (void) test1TaskLongerThanTimeout
{
    __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Test 1: task longer than timeout"];
    [self startAsynchronousTaskWithDuration:4 completionHandler:^(id result, NSError *error) {
        XCTAssertNotNil(result);
        XCTAssertNil(error);
        [expectation fulfill];
    }];
    [self waitForExpectationsWithTimeout:2 handler:nil];
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

XCTestExpectation:如何避免在等待上下文结束后调用fulfill方法? 的相关文章

  • ipython 笔记本的 TOC 扩展发生了什么?

    我正在尝试在新计算机上安装出色的目录扩展 但我再也找不到了 唯一的页面我确实发现 https github com minrk ipython extensions没有解释如何在 Windows 上安装扩展 那么 我该如何安装它 为什么它不

随机推荐