我正在编写一个测试来验证按钮点击发生时是否启动了位置服务。这需要一个非常简单的if语句来确保手机具有可用的位置服务。
现在正在进行的工作测试
- (void)testStartUpdatingLocationInvokedWhenLocationServicesAreEnabled
{
[[[self.locationManager stub] andReturnValue:[NSNumber numberWithBool:true]] locationServicesEnabled];
[[self.locationManager expect] startUpdatingLocation];
[self.sut buttonClickToFindLocation:nil];
[self.locationManager verify];
}
现在经过测试的实现看起来像这样
- (IBAction)buttonClickToFindLocation:(id)sender
{
if ([self.locationManager locationServicesEnabled])
{
[self.locationManager startUpdatingLocation];
}
}
除方法外,所有好的都是deprecated in iOS 4.0。所以现在我需要使用类方法[CLLocationManager locationServicesEnabled]。
问题是我似乎无法找到ocmock是否支持此功能,如果不支持,我现在应该如何解决这个问题。
答案 0 :(得分:3)
@implementation
static BOOL locationManagerExpectedResult;
- (void)testStartUpdatingLocationInvokedWhenLocationServicesAreEnabled
{
locationManagerExpectedResult = YES;
method_exchangeImplementations(
class_getClassMethod([CLLocationManager class], @selector(locationServicesEnabled)) ,
class_getClassMethod([self class], @selector(locationServicesEnabledMock))
);
[self.sut buttonClickToFindLocation:nil];
}
+ (BOOL)locationServicesEnabledMock
{
return locationManagerExpectedResult;
}
@end
编辑:我以为你在验证,但好像你在瞎扯。更新的代码
答案 1 :(得分:2)
最简单的方法是覆盖单元测试类中某个类别中的locationServicesEnabled
:
static BOOL locationServicesEnabled = NO;
@implementation CLLocationManager (UnitTests)
+(BOOL)locationServicesEnabled {
return locationServicesEnabled;
}
@end
...
-(void)tearDown {
// reset to default after each test
locationServicesEnabled = NO;
[super tearDown];
}
它仅在测试时覆盖超类方法,您可以在每次测试中将静态全局设置为适当的值。
或者,您可以将检查包装在您自己的实例方法中,并使用部分模拟。
在被测试的课程中:
-(BOOL)locationServicesEnabled {
return [CLLocationManager locationServicesEnabled];
}
在你的测试中:
-(void)testSomeLocationThing {
MyController *controller = [[MyController alloc] init];
id mockController = [OCMockObject partialMockForObject:controller];
BOOL trackingLocation = YES;
[[[mockController stub] andReturnValue:OCMOCK_VALUE(trackingLocation)] locationServicesEnabled];
// test your controller ...
}
答案 2 :(得分:1)
我不认为这样。我能想到的唯一方法是使用部分mock,然后使用运行时调用来调整你需要的实现。
可行,但很复杂。
更多面向模式的解决方案可能是提取位置服务的检查以支持协议。然后,您可以在测试期间使用模拟执行协议的实现,以根据需要返回YES或NO。由于实际的实现除了返回[CLLocationManager locationServicesEnabled]
之外什么都不做,你可以逃脱而不测试它。
答案 3 :(得分:0)
这是OCMock支持的:
[[[[mockLocationManagerClass stub] classMethod] andReturnValue:OCMOCK_VALUE(YES)] locationServicesEnabled];