How to mock class method (+)? [duplicate]

孤街浪徒 提交于 2019-12-01 06:48:04

Since you can't intercept the method by providing a different instance, what you can do for a class method is provide a different class. Something like this:

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

The point of call then becomes:

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

This introduces a "testing seam," or a point of control, allowing us to specify a class other than SKPaymentQueue. Now let's make a replacement:

static BOOL fakeCanMakePayments;

@interface FakePaymentQueue : SKPaymentQueue
@end

@implementation FakePaymentQueue

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

+ (BOOL)canMakePayments
{
    return fakeCanMakePayments;
}

@end

Strictly speaking, this isn't a "mock object" -- it's a "fake object." The difference is that a mock object verifies how it's called. A fake object just provides stubbed results.

Now let's create a testing subclass of the original class we want to test.

@interface TestingSubclass : OriginalClass
@end

@implementation TestingSubclass

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

@end

So you see, this replaces SKPaymentQueue with FakePaymentQueue. Your tests can now run against TestingSubclass.

One approach is to wrap the class method in your own instance method:

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

Then you mock that method:

-(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];
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!