-- Final Edit: More accurate question Unit Test CLLocationManager implementation
I'm trying to mock CLLocationManagerDelegate to handle users denial about being geolocated
id locationManager = [OCMockObject niceMockForClass:[CLLocationManager class]];
[[[locationManager stub] andReturnValue:@(kCLAuthorizationStatusDenied)] authorizationStatus];
id delegateTarget = [OCMockObject niceMockForProtocol:@protocol(CLLocationManagerDelegate)];
[[delegateTarget expect] locationManager:locationManager didFailWithError:[OCMArg any]];
[locationManager setDelegate:delegateTarget];
[locationManager startUpdatingLocation];
[delegateTarget verify];
However this code doesn't work, I keep getting this error:
Name: NSInternalInconsistencyException File: Unknown Line: Unknown Reason: OCMockObject[CLLocationManagerDelegate]: expected method was not invoked: locationManager:OCMockObject[CLLocationManager] didFailWithError:
How can I be sure that the CLLocationManagerDelegate method locationManager:didFailWithError: is getting called?
Edit: If I use partialMock instead of niceMock for my CLLocationManager instance:
CLLocationManager *trueLocationManager = [[CLLocationManager alloc] init];
id locationManager = [OCMockObject partialMockForObject:trueLocationManager];
[[[locationManager stub] andReturnValue:@(kCLAuthorizationStatusDenied)] authorizationStatus];
id delegateTarget = [OCMockObject mockForProtocol:@protocol(CLLocationManagerDelegate)];
[[delegateTarget expect] locationManager:trueLocationManager didFailWithError:[OCMArg any]];
[locationManager setDelegate:delegateTarget];
[locationManager startUpdatingLocation];
[delegateTarget verify];
I get this:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'OCMockObject[CLLocationManagerDelegate]: unexpected method invoked: locationManager: didChangeAuthorizationStatus:2 expected: locationManager: didFailWithError:'
So I thought I got it and added the code below before my delegateTarget expectation of didFailWithError
[[delegateTarget expect] locationManager:trueLocationManager didChangeAuthorizationStatus:2]; // kCLAuthorizationStatusDenied = 2
And the result is:
Name: NSInternalInconsistencyException File: Unknown Line: Unknown Reason: OCMockObject[CLLocationManagerDelegate] : 2 expected methods were not invoked: locationManager: didChangeAuthorizationStatus:2 locationManager: didFailWithError:
Really don't know what I'm doing wrong...
Edit2: for Ilea Cristian
CLLocationManager *trueLocationManager = [[CLLocationManager alloc] init];
id locationManager = [OCMockObject partialMockForObject:trueLocationManager];
[[[locationManager stub] andReturnValue:@(kCLAuthorizationStatusDenied)] authorizationStatus];
id delegateTarget = [OCMockObject mockForProtocol:@protocol(CLLocationManagerDelegate)];
[[delegateTarget expect] locationManager:locationManager didChangeAuthorizationStatus:2]; // kCLAuthorizationStatusDenied = 2
[[delegateTarget expect] locationManager:locationManager didFailWithError:[OCMArg any]];
[locationManager setDelegate:delegateTarget];
[locationManager startUpdatingLocation];
[delegateTarget verify];
I got this:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'OCMockObject[CLLocationManagerDelegate]: unexpected method invoked: locationManager: didChangeAuthorizationStatus:2 expected: locationManager:OCPartialMockObject[CLLocationManager] didChangeAuthorizationStatus:2 expected: locationManager:OCPartialMockObject[CLLocationManager] didFailWithError:'
Looks like locationManager used in the delegate callback is the trueLocationManager not the locationManager (partialMock)
-- Final Edit: More accurate question Unit Test CLLocationManager implementation
You have created a "nice mock" for your LocationManager. This means that your calls to
setDelegate:
andstartUpdatingLocation
will be silently ignored. You could switch this to a partial mock, but are you just testing the LocationManager? You should only need to test your implementation of the location manager delegate -- you can just call those delegate methods directly.