XCTest Completion Handler Assertion Retain Cycle

216 Views Asked by At

I have been writing Xcode tests using the XCTest framework for a while, mostly async tests of the getters of a service with completion handlers of the following format with no issues:

XCTestExpectation *promise = [self expectationWithDescription:@"Get Something should succeed"];

[self.myService getSomethingOnCompletion:^(NSError * _Nullable error) {
    XCTAssertNil(error, @"Error should be nil");
    [promise fulfill];
}];

[self waitForExpectations:@[promise] timeout:2.0];

Suddenly today I go to write my first async setter test of the below format, but get warnings on the XCTAssert...() statement within the block saying:

Capturing 'self' strongly in this block is likely to lead to a retain cycle

XCTestExpectation *promise = [self expectationWithDescription:@"Set Something should succeed"];

[self.myService setSomething:@"..." onCompletion:^(NSError * _Nullable error) {
    XCTAssertNil(error, @"Error should be nil");
    [promise fulfill];
}];

[self waitForExpectations:@[promise] timeout:2.0];

I've even gone to the lengths of commenting out the entire contents of setSomething: onCompletion: such that it does not do anything, clean and rebuild, yet the warning still persists.

I do not understand what self it is referring to, as the only thing going on inside the block is an XCTAssert...() and [XCTestExpectation fulfill]. Furthermore, I do not understand why none of the 30+ tests I've written of the first format have no warnings associated with them, but all 5+ I've written of the 2nd format do.

Any explanation on what's going on here and how I can resolve it would be appreciated.

(Using Xcode 10.0)

Edit 1:

The issue seems to be with the method name, setSomething: onCompletion:. Changing it to anything else, such as doSomething: onCompletion: removes the warning. I still don't know how/ why Xcode interprets the set command in such a fashion that it presents the warning, so any information would be appreciated.

Edit 2:

The following are the method signatures of setSomething and doSomething:

- (void)setSomething:(EnumType)type onCompletion:(SetSomethingCompletionHandler)completion;
- (void)doSomething:(EnumType)type onCompletion:(SetSomethingCompletionHandler)completion

Where SetSomethingCompletionHandler is defined as :

typedef void (^SetSomethingCompletionHandler)(NSError * _Nullable error);
0

There are 0 best solutions below