5

次のコードの単体テストを記述する必要があります。クラス メソッド canMakePayments のモックを作成したいです。yes または no を返します。これまでのところ、canMakePayments がクラス メソッド (+) であるため、適切なメソッドが見つかりません。すべての OCMock メソッドがすべて使用されているようです。インスタンスメソッド (-)。

皆さん、どんな提案や議論もいただければ幸いです。ありがとう。

// SKPaymentQueue.h
// StoreKit
if ([SKPaymentQueue canMakePayments]){
   ....
}
else{
   ...
}
4

2 に答える 2

14

1 つの方法は、独自のインスタンス メソッドでクラス メソッドをラップすることです。

-(BOOL)canMakePayments {
    return [SKPaymentQueue canMakePayments];
}

次に、そのメソッドをモックします。

-(void)testCanHandlePaymentsDisabled {
    Foo *foo = [[Foo alloc] init];
    id mockFoo = [OCMockObject partialMockForObject:foo];
    BOOL paymentsEnabled = NO;
    [[[mockFoo stub] andReturnValue:OCMOCK_VALUE(paymentsEnabled)] canMakePayments];

    // set up expectations for payments disabled case
    ...

    [foo attemptPurchase];
}
于 2011-12-08T16:48:53.850 に答える
6

別のインスタンスを提供してメソッドをインターセプトすることはできないため、クラス メソッドに対してできることは、別のクラスを提供することです。このようなもの:

+ (Class)paymentQueueClass
{
    return [SKPaymentQueue class];
}

コールポイントは次のようになります。

Class paymentQueueClass = [[self class] paymentQueueClass];
if ([paymentQueueClass canMakePayments])
...

これにより、「テスト シーム」または制御ポイントが導入され、 以外のクラスを指定できるようになりますSKPaymentQueue。では、次のように置き換えてみましょう。

static BOOL fakeCanMakePayments;

@interface FakePaymentQueue : SKPaymentQueue
@end

@implementation FakePaymentQueue

+ (void)setFakeCanMakePayments:(BOOL)fakeValue
{
    fakeCanMakePayments = fakeValue;
}

+ (BOOL)canMakePayments
{
    return fakeCanMakePayments;
}

@end

厳密に言えば、これは「モック オブジェクト」ではなく、「フェイク オブジェクト」です。違いは、モック オブジェクトが呼び出された方法を検証することです。偽のオブジェクトは、スタブ化された結果を提供するだけです。

次に、テストしたい元のクラスのテスト用サブクラスを作成しましょう。

@interface TestingSubclass : OriginalClass
@end

@implementation TestingSubclass

+ (Class)paymentQueueClass
{
    return [FakePaymentQueue class];
}

@end

ご覧のとおり、これは に置き換えSKPaymentQueueられFakePaymentQueueます。テストを に対して実行できるようになりましたTestingSubclass

于 2011-12-08T06:41:48.340 に答える