如何使用 OCMock 验证某个方法从未被调用?

发布于 2024-08-31 10:37:25 字数 630 浏览 14 评论 0原文

在我的日常工作中,我被 Mockito的never()验证,可以确认mock方法从未被调用。

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

At my day job I've been spoiled with Mockito's never() verification, which can confirm that a mock method is never called.

Is there some way to accomplish the same thing using Objective-C and OCMock? I've been using the code below, which works but it feels like a hack. I'm hoping there's a better way...

- (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!");
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

小猫一只 2024-09-07 10:37:26

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

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

id mock = [OCMockObject NiceMockForClass:[SomeClass 类]]

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

[[模拟拒绝] someMethod]

请注意,在快速失败模式下,如果
异常被忽略,它将是
调用 verify 时重新抛出。这
可以确保
来自不需要的调用
可以检测到通知等。

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

Since r69 of OCMock, it's possible to reject a method call http://svn.mulle-kybernetik.com/OCMock/trunk/Source/Changes.txt

Nice mocks / failing fast When a
method is called on a mock object that
has not been set up with either expect
or stub the mock object will raise an
exception. This fail-fast mode can be
turned off by creating a "nice" mock:

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

While nice mocks will simply ignore
all unexpected methods it is possible
to disallow specific methods:

[[mock reject] someMethod]

Note that in fail-fast mode, if the
exception is ignored, it will be
rethrown when verify is called. This
makes it possible to ensure that
unwanted invocations from
notifications etc. can be detected.

Quoted from: http://www.mulle-kybernetik.com/software/OCMock/#features

怎会甘心 2024-09-07 10:37:26

据我所知,当你调用 verify 并调用未记录的方法时,OCMock 会自动失败。如果调用了意外的方法,则不会抱怨的模拟称为“好的模拟”。

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

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

As far as I know OCMock will fail automatically when you call verify and methods that have not been recorded were called. A mock that wouldn't complain if unexpected methods were called is called a "nice mock".

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

    [mock forbiddenMethod];
    [mock verify]; //should fail
}
冷了相思 2024-09-07 10:37:26

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

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

    // exception will raise
    [mock forbiddenMethod];

Starting from version 3.3 OCMock has OCMReject macro.

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

    // exception will raise
    [mock forbiddenMethod];
沧桑㈠ 2024-09-07 10:37:26

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

我为此创建了一个宏:

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

我这样使用它:

[[[_myPartialMock stub] andDoFail] unexpectedMethod];

You may also find it necessary to ensure a method is never being called on an object you are partially mocking.

I created a macro for this:

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

I use it like this:

[[[_myPartialMock stub] andDoFail] unexpectedMethod];
无法言说的痛 2024-09-07 10:37:26

您也可以尝试类似的方法,如 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/

You could also try something like this, a la 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
}

I'm not sure if there are any leaks associated with this code. I got the idea from reading this page: http://thirdcog.eu/pwcblocks/

白首有我共你 2024-09-07 10:37:26

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

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

To make sure your method not called, I think we have to do an assert before the testMethod called. So make sure put OCMReject before you run the test method to listen which method will trigger when runs testMethod:

OCMReject([mock someMethod]);
[mock testMethod];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文