XCTest在使用期望失败时通过

时间:2015-03-31 10:21:58

标签: objective-c xcode xctest xctestexpectation

我正在测试一个在后台运行的方法,并在完成时执行代码块。我正在使用期望来处理测试的异步执行。我写了一个简单的测试来显示行为:

- (void) backgroundMethodWithCallback: (void(^)(void)) callback {
    dispatch_queue_t backgroundQueue;
    backgroundQueue = dispatch_queue_create("background.queue", NULL);
    dispatch_async(backgroundQueue, ^(void) {
        callback();
    });
}

- (void) testMethodWithCallback {
    XCTestExpectation *expectation = [self expectationWithDescription:@"Add collection bundle"];
    [self backgroundMethodWithCallback:^{
        [expectation fulfill];

        usleep(50);
        XCTFail(@"fail test");
    }];
    [self waitForExpectationsWithTimeout: 2 handler:^(NSError *error) {
        if (error != nil) {
            XCTFail(@"timeout");
        }
    }];
}

此测试的XCTFail(@"fail test");行应该失败,但测试正在通过。

我还注意到,这只发生在回调上运行的代码需要一段时间(在我的情况下,我正在检查文件系统上的一些文件)。这就是重现案例所需usleep(50);行的原因。

2 个答案:

答案 0 :(得分:5)

所有测试检查后必须满足期望。将行移动到回调块的末尾足以使测试失败:

- (void) testMethodWithCallback {
    XCTestExpectation *expectation = [self expectationWithDescription:@"Add collection bundle"];
    [self backgroundMethodWithCallback:^{

        usleep(50);
        XCTFail(@"fail test");
        [expectation fulfill];
    }];
    [self waitForExpectationsWithTimeout: 2 handler:^(NSError *error) {
        if (error != nil) {
            XCTFail(@"timeout");
        }
    }];
}

我没有找到关于此的明确文档,但在apple developer guide中,fulfill消息在块的末尾发送,这很有意义。

注意:我首先在swift中找到an example,其中在回调开始时调用fulfill方法。我不知道的是,这个例子是不正确的还是与Objective-C有所不同。

答案 1 :(得分:1)

backgroundMethodWithCallback调用的块立即满足期望,从而让测试在XCTFail被调用之前完成。如果块在完成其他操作之前满足期望,则最终会出现竞争条件,其中测试的行为取决于执行块的其余部分的速度。但是,如果测试本身已经完成,那么就不应该合理地期望XCTFail被捕获。

下划线,如果将[expectation fulfill]移动到块的末尾,则会消除此竞争条件。