Question

I'm writing some tests, where I need to

  • stub a call to a mock CLLocationManager to return a particular CLLocation
  • and in turn that CLLocation needs to have a timestamp that is in the past

Creating instances of CLLocation is easy enough, but the timestamp property on it is read-only and fixed to the point in time when the instance was created. So, I planned to create a mock CLLocation, and stub the timestamp call too.

So, code looks like this:

[[CLLocationManager stubAndReturn:theValue(YES)] locationServicesEnabled];
NSDate *oldDate = [IPPOTestSupportMethods createNSDateSubtractingDays:2];
//TODO - Why is line below failing
[[expectedOldLocationMock stubAndReturn:oldDate] timestamp];
[[locationMgrMock stubAndReturn:expectedOldLocationMock] location];

In summary, I've got a CLLocationManager mock, I create an NSDate that is two days earlier than today. I want that date to be returned when I call

[cllocationmock timestamp];

However, I'm getting and ARC Semantic Issue.

IPPOLocationManagerDelegateImplKiwiTests.m:203:33: Multiple methods named 'timestamp' found with mismatched result, parameter type or attributes

Is this an issue in Kiwi, or am I missing something?

Was it helpful?

Solution

I was able to make this work by using the selector-stubbing technique instead of the message pattern technique:

[expectedOldLocationMock stub:@selector(timestamp) andReturn:oldDate];

I get the same error as you when using the message pattern technique (stubAndReturn:):

Multiple methods named 'timestamp' found with mismatched result, parameter type or attributes

If you inspect this error in the Issue Navigator, you should see that it points to two different classes that declare a timestamp selector: class UIAcceleration declares

@property(nonatomic,readonly) NSTimeInterval timestamp;

…and class CLLocation declares

@property(readonly, nonatomic) NSDate *timestamp;

Note the structure of the "message pattern" stubbing technique:

[[someObject stubAndReturn:expectedValue] messageToStub]

The stubAndReturn: method returns an opaque object of type id. Thus, it's equivalent to this:

id invocationCapturer = [someObject stubAndReturn:expectedValue];
[invocationCapturer messageToStub];

Here, "messageToStub" is your timestamp selector. So you're saying to send the message timestamp to an unknown object of type id. Since at compile time we make no assertion about the type of the object being sent the timestamp selector, it can't know which version of that timestamp property you mean, and thus it can't determine the correct return type.

You can reproduce the same error by simply doing this:

id someUnknownObject;
[someUnknownObject timestamp];

The conclusion is that the message-pattern stubbing technique just won't work well when there are different declarations visible of the same selector name.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top