目标C& OC Mock - 模拟一个类方法?

时间:2011-04-08 19:52:59

标签: objective-c unit-testing mocking class-method ocmock

我需要能够确定是否调用了类方法。 我怎么能用OCMock做到这一点?

4 个答案:

答案 0 :(得分:6)

从OCMock版本2.1开始,这支持开箱即用。您现在可以使用与存根实例方法相同的方式存根类方法。

答案 1 :(得分:3)

一种方法是将class方法包装在您自己的类中的方法中。因此,假设您的班级必须致电[SomeOtherClass classMethod:someString]。您可以在类上创建方法invokeClassMethod:,如下所示:

-(NSString *)invokeClassMethod:(NSString *)someString {
    return [SomeOtherClass classMethod:someString];
}

然后在测试中,您创建一个部分模拟并期望invokeClassMethod:

-(void)testSomething {
    id partialMock = [OCMockObject partialMockForObject:actual];
    [[[partialMock expect] andReturn:@"foo"] invokeClassMethod:@"bar"];

    [actual doSomething:@"bar"];

    [partialMock verify];
}

如果您想验证invokeClassMethod 未被调用,可以抛出异常:

-(void)testSomethingElse {
    id partialMock = [OCMockObject partialMockForObject:actual];
    [[[partialMock stub] andThrow:[NSException exceptionWithName:@"foo" reason:@"Should not have called invokeClassMethod:" userInfo:nil] invokeClassMethod:OCMOCK_ANY];

    [actual doSomething:@"bar"];
}

如果调用invokeClassMethod,则激活将导致测试失败。

答案 2 :(得分:2)

正如zneak在对您的问题的评论中提到的那样,请查看this answer

从那里的评论中,结帐this block-based implementation类方法调整。

OCMock似乎没有直接支持您想要做的事情,但这个解决方案非常好!

答案 3 :(得分:1)

或者,假设你有这个类:

@interface ABCCleverClass : NSObject
+ (id)specialMethod;
@end

并且您想要模拟此类方法。一种选择是在此类上创建一个类别,用于定义和实现测试支持。然后,您可以将测试类中的类方法的实现与类别中的模拟方法交换。

#import <objc/runtime.h>

@interface ABCCleverClass (TestSupport)
+ (id)mockSpecialMethod;
@end

@implementation ABCCleverClass (TestSupport)

+ (void)load {
  Method original = class_getClassMethod([ABCCleverClass class], @selector(specialMethod));
  Method mocked = class_getClassMethod([ABCCleverClass class], @selector(mockSpecialMethod));
  method_exchangeImplementations(original, mocked);
}

+ (id)mockSpecialMethod {
  // Perform mock method. You may need to add more class methods
  // in order to configure this.
}

@end