Search code examples
iosunit-testingasynchronouspromisekitxctestexpectation

Unit testing code with PromiseKit usage


I'm trying to test Diary class that has dependency to Network.

So Diary code:

- (PMKPromise *)saveAndUploadToServer:(DiaryItem *)item
{
    return [self save:item].then(^{
        return [self upload:item]; << See UPDATE //I put breakpoint here, it is never called
    });
}

- (PMKPromise *)save:(DiaryItem *)item
{
    return [PMKPromise new:^(PMKPromiseFulfiller fulfill, PMKPromiseRejecter reject) {
        [self.entryCreationManagedContext performBlock:^{
            BOOL success;
            NSError *saveError = nil;

            item.status = @(UploadingStatus);
            success = [self.entryCreationManagedContext save:&saveError];

            if (success) {
                fulfill(item.objectID);
            }
            else {
                reject(saveError);
            }
        }];
    }];
}

- (PMKPromise*)upload:(DiaryItem*)item
{
    return [self.network POST:self.diaryUrl parameters:[item dictionary]].then(^{
         return [self reportUploadAnalytics];
    });
}

And the test:

- (void)testFailedUploadingReportsAnalytics
{
    XCTestExpectation *expectation = [self expectationWithDescription:@"Operations completed"];

    [self uploadToServerAndReturnCallback].finally(^{
        [expectation fulfill];
    });

    [self waitForExpectationsWithTimeout:5 handler:^(NSError *error) {
        assertThat(error, is(nilValue()));

        //check that mock called
    }];
}

The Network is mock in this test. But what I see that chain of promises is not executed. It stuck. Maybe because then: block is called on main thread as well XCTest is pausing it. But at the same time it should probably continue after 5 sec. What can be the issue?

UPDATE

Looks like it is nothing with my original assumption. If I replace [self.entryCreationManagedContext save:&saveError] with YES then debug reaches breakpoint.

UPDATE 2

It looks like issue with this particular saving of managed context. It is triggering notification about synchronising another managed contexts. And we are discovering what else there.


Solution

  • It is ended up in different issue and nothing connected to PromiseKit.

    We discovered growing amount of used memory. That NSManagedObjectContextDidSaveNotification was producing deadlock on different store coordinators. After fixing that tests started working as expected.