1

単体テストで OCMocks を使用する方法を学んでおり、基本を理解しています。ただし、クラス メソッドの呼び出しをモックする方法がわかりません。

私がしたい:

[[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
4

3 に答える 3

3

シングルトンのモックはトリッキーです。いくつかの実行時マジックでそれを行うことができます。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];
}

しばらく前に、このアプローチのより詳細な記事を書きました。

于 2013-04-12T16:40:40.613 に答える
0

別の方法として、両方のバリアントをテストに入れ、iPhone および iPad シミュレーターでテストを実行します。確かに、これは少し面倒です。

-(void)testShouldDoSomething {
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        // test iPad behavior
    } else {
        // test iPhone behavior
    }
}
于 2013-04-12T16:47:02.287 に答える