erikdoe / ocmock

Mock objects for Objective-C
http://ocmock.org
Apache License 2.0
2.16k stars 606 forks source link

OCMVerify passes when it should fail with mock returning mock #304

Closed lyahdav closed 7 years ago

lyahdav commented 8 years ago

Given the following classes:

@interface Bar: NSObject
- (void)baz;
@end

@implementation Bar
- (void)baz {
}
@end

@interface Foo: NSObject
@property (nonatomic) Bar *bar;
@end

@implementation Foo
@end

And given the following unit test:

    Foo *foo = OCMClassMock([Foo class]);
    Bar *bar = OCMClassMock([Bar class]);
    OCMStub([foo bar]).andReturn(bar);
    [foo bar];
    OCMVerify([foo.bar baz]);

The test passes, but I expect it to fail because baz was never called on bar. I can get the test to fail if I change the OCMVerify line to: OCMVerify([bar baz]);

If I delete the [foo bar] line, instead I get a failure: OCMockObject(Foo): Method bar was not invoked.

This error is strange because I am trying to verify that baz was called, yet the error mentions bar. Is it possible this is because OCMVerify verifies the first method call in the macro?

erikdoe commented 7 years ago

Apologies, I could have sworn that I had replied to this issue. That said, you are correct that OCMVerify verifies the invocation of bar on foo. There's only so much you can do with macros and runtime trickery. As soon as code is executed inside the OCMVerify macro, OCMock has to assume you want to verify those invocations. How else would it know not to verify the first invocation (of bar) but to verify the second one (of baz)? Even a convention that would say that only the last invocation is meant to be verified seems impossible to implement, because how would OCMock know at the point when bar is invoked that there will be another invocation in the future?