如何模拟类方法(+)?

时间:2011-12-08 06:24:52

标签: objective-c unit-testing mocking static-methods ocmock

需要为下面的代码编写单元测试,我想为类方法做模拟canMakePayments,返回yes或no,到目前为止没有好方法找到会员,canMakePayments是一个类方法(+),似乎所有的OCMock方法都是全部用于例如方法( - )。

你们有任何建议或讨论将不胜感激。谢谢。

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

2 个答案:

答案 0 :(得分:13)

一种方法是将class方法包装在您自己的实例方法中:

-(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];
}

答案 1 :(得分:4)

由于您无法通过提供不同的实例来拦截该方法,因此您可以为类方法执行的操作是提供不同的类。像这样:

+ (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运行。