模拟单例是很棘手的。你可以用一些运行时魔法来做到这一点。可以借助Matt Gallagher 的 invokeSupersequent 宏来完成。基本上,您将一个类别添加到您的测试用例中,该类别将覆盖currentDevice
以返回一个模拟,前提是您已经设置了模拟。这是设置:
#import "NSObject+SupersequentImplementation.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
@implementation UIDevice (UnitTests)
+(id)currentDevice {
if ([BaseTestCase mockDevice]) {
return [BaseTestCase mockDevice];
}
return invokeSupersequentNoArgs();
}
@end
#pragma clang diagnostic pop
static id mockDevice = nil;
+(id)mockDevice {
return mockDevice;
}
+(id)createMockDevice {
mockDevice = [OCMockObject mockForClass:[UIDevice class]];
return mockDevice;
}
+(id)createNiceMockDevice {
mockDevice = [OCMockObject niceMockForClass:[UIDevice class]];
return mockDevice;
}
-(void)tearDown {
mockDevice = nil;
[super tearDown];
}
然后,在您的测试中:
-(void)testShouldDoSomethingOnIpad {
id mockDevice = [BaseTestCase createNiceMockDevice];
[[[mockDevice stub] andReturnValue:OCMOCK_VALUE(UIUserInterfaceIdiomPad)] userInterfaceIdiom];
// do something iPad-specific
[mockDevice verify];
}
不久前,我对这种方法进行了更详细的描述。