This question already has an answer here:
Need to write unit testing for the following code, I want to do mock for class method canMakePayments, return yes or no, so far no good method found dues to canMakePayments is a class method (+), seems all OCMock methods are all used for instance method (-).
You guys any suggestion or discussion will be appreciated. Thanks.
// SKPaymentQueue.h
// StoreKit
if ([SKPaymentQueue canMakePayments]){
....
}
else{
...
}
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];
}
来源:https://stackoverflow.com/questions/8427044/how-to-mock-class-method