Цель C & OC Mock - издеваться над методом класса? - PullRequest
4 голосов
/ 08 апреля 2011

Мне нужно иметь возможность определить, был ли вызван метод класса или нет.Как я могу сделать это с OCMock?

Ответы [ 4 ]

6 голосов
/ 17 марта 2013

Начиная с выпуска 2.1 OCMock это поддерживается "из коробки". Теперь вы можете заглушить методы класса таким же образом, как и методы экземпляра заглушки.

3 голосов
/ 11 апреля 2011

Один из подходов заключается в том, чтобы обернуть метод класса в метод своего собственного класса.Допустим, ваш класс должен позвонить [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 голосов
/ 02 июля 2012

Как упоминал zneak в своем комментарии к вашему вопросу, взгляните на этот ответ ,

И из комментариев, приведенных здесь, отметьте эту реализацию на основе блоков метода класса Swizzling.

OCMock не поддерживает напрямую то, что вы хотите сделать, но это решение довольно приятно!

1 голос
/ 06 октября 2013

В качестве альтернативы предположим, что у вас есть класс:

@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
...