Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/120.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 使用OCMock模拟[[UIDevice currentDevice]userInterfaceIdiom]_Ios_Unit Testing_Ocmock - Fatal编程技术网

Ios 使用OCMock模拟[[UIDevice currentDevice]userInterfaceIdiom]

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

我正在学习在单元测试中使用OCMock,并且我了解基本知识。但是,我不确定如何模拟对类方法的调用

我想要:

[[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。这完全取决于你在测试什么,以及你想允许多少“真实”的行为。