Search code examples
iosunit-testingxctestxctestexpectation

Correct timing/placement of XCTestExpectation fulfill method call in unit tests?


Consider the following unit test:

- (void)testSample {
    XCTestExpectation *expectation = [self expectationWithDescription:@"Sample"];

    [self.manager loadAllSuccess:^{
        [expectation fulfill];

        NSArray *data = [self.manager dataForIndex:0];

        // Correct count of data is 10, not 44 - this should fail.
        XCTAssertEqual(44, data.count);
    } failure:^(NSError *error) {
        [expectation fulfill];

        XCTFail(@"Error encountered");
    }];

    [self waitForExpectationsWithTimeout:60 handler:nil];
}

I am encountering some issues with the known failure case. The test finishes successfully, despite the fact that there are only supposed to be 10 items in the data array.

If I put the [expectation fulfill] call at the bottom of the block, after the XCTAssertEqual(44, data.count) method call, the test works as expected and fails until I correct the value to be 10.

Is this a known issue? I've been unable to read documentation saying that I should be calling that at the very last minute...


Solution

  • According to http://nshipster.com/xctestcase/

    Always call fulfill() at the end of the asynchronous callback—fulfilling the expectation earlier can set up a race condition where the run loop may exit before completing the test. If the test has more than one expectation, it will not pass unless each expectation executes fulfill() within the timeout specified in waitForExpectationsWithTimeout().

    Just found this - not sure if it's 100% accurate though as I cannot see any other documentation stating this elsewhere.