如何使用OCMock验证方法永远不会被调用?

时间:2010-04-29 16:43:43

标签: objective-c cocoa mocking mockito ocmock

在我的日常工作中,我被Mockito's never() verification宠坏了,这可以确认永远不会调用模拟方法。

有没有办法用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!");
}

6 个答案:

答案 0 :(得分:61)

自OCMock的r69以来,可以拒绝方法调用http://svn.mulle-kybernetik.com/OCMock/trunk/Source/Changes.txt

  

好的模拟/快速失败当a   方法在模拟对象上调用   没有任何期望   或存根模拟对象将引发一个   例外。这种失败快速模式可以   通过创建一个“漂亮”的模拟来关闭:

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

虽然好的模拟只会忽略   所有意想不到的方法都有可能   禁止特定方法:

[[mock reject] someMethod]
     

请注意,在故障快速模式下,如果是   异常被忽略,它将是   调用verify时重新抛出。这个   可以确保这一点   来自的不受欢迎的调用   可以检测到通知等。

引自:http://www.mulle-kybernetik.com/software/OCMock/#features

答案 1 :(得分:19)

据我所知,当您调用verify时,OCMock将自动失败,并且调用了尚未记录的方法。如果调用意外方法就不会抱怨的模拟被称为“漂亮的模拟”。

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

    [mock forbiddenMethod];
    [mock verify]; //should fail
}

答案 2 :(得分:7)

从版本3.3开始,OCMock具有OCMReject宏。

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

    // exception will raise
    [mock forbiddenMethod];

答案 3 :(得分:3)

您可能还发现有必要确保永远不会在您正在部分嘲笑的对象上调用方法。

我为此创建了一个宏:

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

我这样用:

[[[_myPartialMock stub] andDoFail] unexpectedMethod];

答案 4 :(得分:0)

你也可以尝试这样的东西,一个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/

答案 5 :(得分:0)

为了确保你的方法没有被调用,我认为我们必须在调用testMethod之前做一个断言。因此,在运行测试方法之前确保放置OCMReject以监听运行testMethod时将触发的方法:

OCMReject([mock someMethod]);
[mock testMethod];