I would like to test that a method is called twice, the first time passing YES
for a parameter, the second time NO
.
What complicates things is that the method I would like to test is a class method, I'm not sure whether this has anything to do with the issue I'm seeing.
My test looks like this:
- (void)testCreatesMessagesWithCorrectHTMLForcing {
id messageClassMock = OCMClassMock([MyMessage class]);
[messageClassMock setExpectationOrderMatters:YES];
[[[messageClassMock expect] andForwardToRealObject] messageForDictionary:[OCMArg any]
forceHTMLRendering:YES
inContext:[OCMArg any]];
[[[messageClassMock expect] andForwardToRealObject] messageForDictionary:[OCMArg any]
forceHTMLRendering:NO
inContext:[OCMArg any]];
NSMutableDictionary *mockJSON = [self.mockJSON mutableCopy];
MyThread *classUnderTest = [MyThread threadForDictionary:mockJSON
inContext:self.mockContext];
OCMVerifyAll(messageClassMock);
[messageClassMock stopMocking];
}
The threadForDictionary:inContext:
method calls the messageForDictionary:forceHTMLRendering:inContext:
for each message in the thread and needs an object as return value. That's why I added andForwardToRealObject
, otherwise I get exceptions because of the return value being nil
. As you can imagine from the signatures it's about parsing JSON to CoreData objects.
Adding this test makes all other tests in the same test file fail with the following message
unexpected method invoked: messageForDictionary:<OCMAnyConstraint: 0x7fab637063d0> forceHTMLRendering:NO inContext:<OCMAnyConstraint: 0x7fab63706eb0>
expected: messageForDictionary:<OCMAnyConstraint: 0x7fab6371cb20> forceHTMLRendering:YES inContext:<OCMAnyConstraint: 0x7fab6371fb50>"
I don't get why this happens as I call stopMocking
in the end so the other tests should not be affected.
The following changes make the other tests run correctly:
- Remove any of the two expectations. It doesn't matter which of two it is as long as there is only one.
- Renaming the method to
testZ
. This way it's alphabetically after the other tests in the same file; thus, executed last and doesn't seem to affect them anymore.
As the setExpectationOrderMatters:YES
does not seem to work I tried to check the order myself doing this:
- (void)testCreatesMessagesWithCorrectHTMLForcing {
id messageClassMock = OCMClassMock([MyMessage class]);
__block BOOL firstInvocation = YES;
[[[messageClassMock expect] andForwardToRealObject] messageForDictionary:[OCMArg any]
forceHTMLRendering:[OCMArg checkWithBlock:^BOOL (id obj) {
NSNumber *boolNumber = obj;
expect([boolNumber boolValue]).to.equal(firstInvocation);
firstInvocation = NO;
return YES;
}]
inContext:[OCMArg any]];
NSMutableDictionary *mockJSON = [self.mockJSON mutableCopy];
MyThread *classUnderTest = [MyThread threadForDictionary:mockJSON
inContext:self.mockContext];
expect(firstInvocation).to.equal(NO);
OCMVerifyAll(messageClassMock);
[messageClassMock stopMocking];
}
But the checkWithBlock:
does not seem to be called. (The test fails at expect(firstInvocation).to.equal(NO);
)
What's going on here?
Is there another (better?) way to write a test with OCMock that checks whether the method is called with the correct parameters in the correct order?