Ios 使用OCMock模拟[[UIDevice currentDevice]userInterfaceIdiom]
我正在学习在单元测试中使用OCMock,并且我了解基本知识。但是,我不确定如何模拟对类方法的调用 我想要:Ios 使用OCMock模拟[[UIDevice currentDevice]userInterfaceIdiom],ios,unit-testing,ocmock,Ios,Unit Testing,Ocmock,我正在学习在单元测试中使用OCMock,并且我了解基本知识。但是,我不确定如何模拟对类方法的调用 我想要: [[UIDevice currentDevice] userInterfaceIdiom] 为我的测试用例返回不同(但有效)的接口习惯用法 id mock = [OCMockObject mockForClass:[UIDevice class]]; // Would I use a mock or a stub to have UIDevice mock return // curr
[[UIDevice currentDevice] userInterfaceIdiom]
为我的测试用例返回不同(但有效)的接口习惯用法
id mock = [OCMockObject mockForClass:[UIDevice class]];
// Would I use a mock or a stub to have UIDevice mock return
// currentDevice and then from it, return userInterfaceIdiom
嘲笑单身汉是很棘手的。您可以使用一些运行时魔法来实现这一点。这是有可能做到的帮助。基本上,您向测试用例添加一个类别,该类别覆盖
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];
}
不久前我做过。嘲笑单身汉是很棘手的。您可以使用一些运行时魔法来实现这一点。这是有可能做到的帮助。基本上,您向测试用例添加一个类别,该类别覆盖
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];
}
不久前我做过。另一种方法是将这两种变体都放在测试中,然后在iPhone和iPad模拟器中运行测试。诚然,这有点麻烦
-(void)testShouldDoSomething {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// test iPad behavior
} else {
// test iPhone behavior
}
}
另一种方法是将这两种变体放在测试中,并在iPhone和iPad模拟器中运行测试。诚然,这有点麻烦
-(void)testShouldDoSomething {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// test iPad behavior
} else {
// test iPhone behavior
}
}
以下是一个简单的解决方案:
OCMockObject* _deviceMock = OCMPartialMock([UIDevice currentDevice]);
[[[_deviceMock stub] andReturnValue:@(UIUserInterfaceIdiomPad)] userInterfaceIdiom];
只需确保行为中的代码使用此检查即可
[UIDevice currentDevice].userInterfaceIdiom
而不是宏
UI_USER_INTERFACE_IDIOM()
以下是一个简单的解决方案:
OCMockObject* _deviceMock = OCMPartialMock([UIDevice currentDevice]);
[[[_deviceMock stub] andReturnValue:@(UIUserInterfaceIdiomPad)] userInterfaceIdiom];
只需确保行为中的代码使用此检查即可
[UIDevice currentDevice].userInterfaceIdiom
而不是宏
UI_USER_INTERFACE_IDIOM()
我认为这是最好的解决办法。无论如何,测试都应该在两个设备上运行。我认为这是最好的解决方案。无论如何,测试都应该在这两台设备上运行。感谢您的回答和非常有用的写作。尽管做了前期工作,我认为这个解决方案更适合测试。使用niceMock而不是常规mock的原因是什么?有时测试中的某些内容会产生副作用,调用
UIDevice
properties。你可以从不用nice mock开始,如果你需要的话,把它换成nice mock。这完全取决于你在测试什么,以及你想允许多少“真实”的行为。谢谢你的回答和令人难以置信的帮助。尽管做了前期工作,我认为这个解决方案更适合测试。使用niceMock而不是常规mock的原因是什么?有时测试中的某些内容会产生副作用,调用UIDevice
properties。你可以从不用nice mock开始,如果你需要的话,把它换成nice mock。这完全取决于你在测试什么,以及你想允许多少“真实”的行为。