Since you cannot intercept a method by providing another instance, what you can do for a class method is to provide another class. Something like that:
+ (Class)paymentQueueClass { return [SKPaymentQueue class]; }
Then the dial peer becomes:
Class paymentQueueClass = [[self class] paymentQueueClass]; if ([paymentQueueClass canMakePayments]) ...
A “test seam” or control point is entered here to specify a class other than SKPaymentQueue . Now 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 is not an “object layout” - it is a “fake object”. The difference is that the layout of the object checks how it is called. A fake object simply provides sealed results.
Now create a subclass for testing the source 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 . Now your tests can work against TestingSubclass .
source share