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

На моей основной работе я был избалован Проверка Mockito never(), которая может подтвердить, что фиктивный метод никогда не вызывается.

Есть ли способ сделать то же самое, используя Objective-C и OCMock? Я использовал приведенный ниже код, который работает, но это похоже на взлом. Я надеюсь, что есть лучший способ...

- (void)testSomeMethodIsNeverCalled {
    id mock = [OCMockObject mockForClass:[MyObject class]];
    [[[mock stub] andCall:@selector(fail) onObject:self] forbiddenMethod];

    // more test things here, which hopefully
    // never call [mock forbiddenMethod]...
}

- (void)fail {
    STFail(@"This method is forbidden!");
}

person Justin Voss    schedule 29.04.2010    source источник


Ответы (6)


Начиная с версии 69 OCMock можно отклонить вызов метода http://svn.mulle-kybernetik.com/OCMock/trunk/Source/Changes.txt

Хорошие макеты / быстрый сбой Когда метод вызывается для макета объекта, который не был настроен ни с ожиданием, ни с заглушкой, макет объекта вызовет исключение. Этот отказоустойчивый режим можно отключить, создав «хороший» макет:

id mock = [OCMockObject niceMockForClass:[SomeClass class]]

В то время как хорошие моки будут просто игнорировать все неожиданные методы, можно запретить определенные методы:

[[mock reject] someMethod]

Обратите внимание, что в отказоустойчивом режиме, если исключение игнорируется, оно будет сгенерировано повторно при вызове проверки. Это позволяет гарантировать обнаружение нежелательных вызовов из уведомлений и т. д.

Цитата из: http://www.mulle-kybernetik.com/software/OCMock/#features

person InsertWittyName    schedule 18.04.2011

Насколько я знаю, OCMock автоматически выйдет из строя, когда вы вызовете проверку и были вызваны методы, которые не были записаны. Макет, который не будет жаловаться, если будут вызваны неожиданные методы, называется «хороший макет».

- (void)testSomeMethodIsNeverCalled {
    id mock = [OCMockObject mockForClass:[MyObject class]];

    [mock forbiddenMethod];
    [mock verify]; //should fail
}
person Johannes Rudolph    schedule 02.05.2010
comment
Это полностью сработало! Я не ожидал, что это будет так просто. Просто чтобы сыграть в адвоката дьявола, вы думаете, что это скрывает цель теста? - person Justin Voss; 03.05.2010
comment
@Justin: Ну, в этом случае читатель должен знать о поведении OCMock, что не так уж очевидно. Помещения комментария рядом с фиктивным вызовом проверки должно быть достаточно, чтобы прояснить, что должно произойти. Нравится: // verify should fail because we called an unexpected method on the mock. - person Johannes Rudolph; 04.05.2010

Начиная с версии 3.3 OCMock имеет макрос OCMReject.

    id mock = OCMClassMock([MyObject class]);
    OCMReject([mock forbiddenMethod]);

    // exception will raise
    [mock forbiddenMethod];
person Ruslan Mansurov    schedule 27.04.2016

Вы также можете счесть необходимым обеспечить, чтобы метод никогда не вызывался для объекта, который вы частично имитируете.

Я создал макрос для этого:

#define andDoFail andDo:^(NSInvocation *invocation) { STFail(@"Should not have called this method!"); }

Я использую это так:

[[[_myPartialMock stub] andDoFail] unexpectedMethod];
person Ben Flynn    schedule 18.04.2013
comment
Если вы используете современный OCMock, я рекомендую использовать reject, как указано в других ответах. - person Ben Flynn; 13.07.2015

Вы также можете попробовать что-то вроде этого, а-ля JavaScript:

- (void)aMethod {
   __block BOOL b = NO;

   id mock = [OCMockObject mockForClass:[UIView class]];
   [[[mock stub] andDo:^(NSInvocation *i) { b = YES; }] resignFirstResponder];
   [mock resignFirstResponder];

   NSLog(@"And b is: %i", b); // This reads "And b is: 1" on the console
}

Я не уверен, есть ли какие-либо утечки, связанные с этим кодом. Я понял эту идею, прочитав эту страницу: http://Thirdcog.eu/pwcblocks/

person Antoni    schedule 23.02.2011

Чтобы убедиться, что ваш метод не вызывается, я думаю, мы должны сделать утверждение до вызова testMethod. Поэтому убедитесь, что поставили OCMReject перед запуском тестового метода, чтобы узнать, какой метод сработает при запуске testMethod:

OCMReject([mock someMethod]);
[mock testMethod];
person Tai Le    schedule 29.08.2017
comment
Хотя этот фрагмент кода может решить проблему, он не объясняет, почему и как отвечает на вопрос. Пожалуйста, включите объяснение кода, так как это действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос для будущих читателей, и эти люди могут не знать причин вашего предложения кода. Отметчики/рецензенты: За ответы, содержащие только код, такие как этот, голосуйте против, не удаляйте! - person Patrick; 29.08.2017