CLLocationManagerDelegate

CLLocationManagerDelegate

-最终编辑:
更准确的问题Unit Test CLLocationManager implementation

我正在尝试模拟CLLocationManagerDelegate以处理拒绝用户进行地理位置定位的问题

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];

但是此代码不起作用,我不断收到此错误:

名称:NSInternalInconsistencyException
文件:未知
行:未知
原因:OCMockObject [CLLocationManagerDelegate]:未调用预期方法:locationManager:OCMockObject [CLLocationManager] didFailWithError:

如何确定CLLocationManagerDelegate方法locationManager:didFailWithError:被调用?

编辑:
如果我对我的CLLocationManager实例使用partialMock而不是niceMock:
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];

我得到这个:

由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'OCMockObject [CLLocationManagerDelegate]:调用了意外方法:locationManager:didChangeAuthorizationStatus:2
预期:locationManager:didFailWithError:'

所以我想我明白了,并在我的didTarget期望didFailWithError之前添加了以下代码
[[delegateTarget expect] locationManager:trueLocationManager didChangeAuthorizationStatus:2]; // kCLAuthorizationStatusDenied = 2

结果是:

名称:NSInternalInconsistencyException
文件:未知
行:未知
原因:OCMockObject [CLLocationManagerDelegate]:未调用2个预期方法:
locationManager:didChangeAuthorizationStatus:2
locationManager:didFailWithError:

真的不知道我在做什么错...

Edit2:针对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];

我懂了:

由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'OCMockObject [CLLocationManagerDelegate]:调用了意外方法:locationManager:didChangeAuthorizationStatus:2
预期:locationManager:OCPartialMockObject [CLLocationManager] didChangeAuthorizationStatus:2
预期:locationManager:OCPartialMockObject [CLLocationManager] didFailWithError:'

看起来在委托回调中使用的locationManager是trueLocationManager而不是locationManager(partialMock)

-最终编辑:
更准确的问题Unit Test CLLocationManager implementation

最佳答案

您有这行:

[locationManager setDelegate:delegateTarget];

这意味着,当调用locationManager:didFailWithError:时,传递给CLLocationManager参数的对象将是名为locationManager-AND NOT trueLocationManager的OCMock对象。

您的期望:
[[delegateTarget expect] locationManager:trueLocationManager didFailWithError:[OCMArg any]];

因此,您期望通过trueLocationManager的调用,但是会传递部分模拟。尝试期望部分模拟通过。

OCMock部分模拟,例如locationManager,只是真实对象的代理包装,但是它们的类型不同(这就是为什么您使用id而不是真实类型的原因)。

之所以如此有效,是因为Objective-C通过消息传递处理 call 的方式。如果您阅读了有关NSProxy的文章,然后看了一下OCMock implementation,您将真正理解一些后台工作原理。

编辑:

我个人不知道您真正想测试什么。苹果框架?没有实体存在您的类/协议。你在测试什么?

我猜您有一个实现CLLocationManagerDelegate协议的ViewController。模拟那个 class 。如果您的位置管理器是一个属性,请将其存根以返回您的伪造的位置管理器(以便内部vc使用伪造的)。或将伪造的locationManager.delegate设置为您的ViewController。启动伪造的位置管理器。

期望ViewControllers委托方法被调用。如果您的位置管理员是单身人士,则it's a bit tricky to replace it带有假冒/存根。

10-07 20:04