How to use OCMock to verify that an asynchronous method does not get called in Objective C? - objective-c

I want to verify that a function is not called. The function is executed in an asynchronous block call inside the tested function and therefore OCMReject() does not work.
The way I have tested if async functions are indeed called would be as follows:
id mock = OCMClassMock([SomeClass class]);
OCMExpect([mock methodThatShouoldExecute]);
OCMVerifyAllWithDelay(mock, 1);
How would a test be done to test if a forbidden function is not called?
Something like:
VerifyNotCalled([mock methodThatShouoldExecute]);
OCMVerifyAllWithDelay(mock, 1);

I would recommend using an OCMStrictClassMock instead of the OCMClassMock (which gives you a nice mock). A strict mock will instantly fail your test if any method is called on it that you did not stub or expect, which makes your tests a lot more rigorous.
If that's not an option for you, you can do what you described with:
OCMReject([mock methodThatShouoldExecute]);
See the "Failing fast for regular (nice) mocks" section in the OCMock docs.
Now as for waiting for your code which may call the forbidden method, that's another matter. You can't use OCMVerifyAllWithDelay since that returns immediately as soon as all expectations are met, it doesn't wait around a full second to see if illegal calls will be made to it. One option is to put a 1 second wait before verifying the mock each time. Ideally, you could also wait explicitly on your asynchronous task with an XCTestExpectation. Something like:
XCTestExpectation *asyncTaskCompleted = [self expectationWithDescription:#"asyncTask"];
// Enqueued, in an onCompletion block, or whatever call
// ... [asyncTaskCompleted fulfill]
[self waitForExpectationsWithTimeout:1 handler:nil]

Related

Mockito - Is it possible to deep mock a void method call to do nothing?

I wanted to know if it is possible to "deep mock" a void method call without breaking out the call chain, using Mockito.
This is an example for the original call I want to mock:
obj.getSomething().add(3);
where "add"'s return type is void.
I tried:
doNothing().when(obj).getSomething().add(3)
and:
doNothing().when(obj.getSomething()).add(3) //wont work since "when" expects a mock.
I also failed using Mockito.when(...) since it does not work with void methods.
I do not want to break the call up since it will be very cumbersome for fluent API calls that are much longer.
Is there an official solution / workaround for this scenario?
Thanks :)
If the value returned by getSomething is not a mock, it won't work.
Return value of getSomething should be a mock and it will allow to assign mock behavior for that value.
Something someMock = mock(Something.class);
when(obj.getSomething()).thenReturn(someMock);
doNothing().when(someMock).add(3);

Calling OCMStub and OCMReject on the same method

I've been attempting to write some fail fast tests using OCMReject. However I've found that if OCMStub is used in conjunction with OCMReject, this test will pass
id _mockModel = OCMProtocolMock( #protocol( CTPrefModelProtocol));
//It doesn't seem to matter what order these two are in, the test behaves the same
OCMStub([_mockModel getPreferences]);
OCMReject([_mockModel getPreferences]);
[_mockModel getPreferences];
Even though it should clearly fail because I'm calling the function that I've set in the OCMReject method.
I realise I can just stub getPreferences whenever I'm expecting a result from it and remove it from this test, but largely that means if I've set a stub on getPreferences in my setUp method, any test that calls OCMReject([_mockModel getPreferences]) will just be ignored.
Why am I not able to use OCMStub and OCMReject together? Is it because OCMStub alters getPreferences somehow and as a result whenever I call this method, it actually calls some other method instead?
So apparently I can't read. Reading through the OCMock 3 Documentation, under the limitations heading 10.2
Setting up expect after stub on the same method does not work
id mock = OCMStrictClassMock([SomeClass class]);
OCMStub([mock someMethod]).andReturn(#"a string");
OCMExpect([mock someMethod]);
/* run code under test */
OCMVerifyAll(mock); // will complain that someMethod has not been called
The code above first sets up a stub for someMethod and afterwards an
expectation for the same method. Due to the way mock objects are
currently implemented any calls to someMethod are handled by the stub.
This means that even if the method is called the verify fails. It is
possible to avoid this problem by adding andReturn to the expect
statement. You can also set up a stub after the expect.
I suspect this same limitation exists for OCMReject as well. Hopefully this helps equally blind people like myself. A link to the documentation for the lazy.

OCMock and overriding stub value

mockModule = OCMPartialMock(module);
OCMStub([mockModule send:#"FOO"]).andReturn(YES);
OCMStub([mockModule send:#"FOO"]).andReturn(NO);
In this example I have a simple mock module, and I set some stubs to return YES/NO when sent a String, the problem that occurs is that if I set the same string twice it only returns the first value, and not the new value.
In this example about the problem is demonstrated like so I would expect a call such as:
BOOL answer = [module send:#"FOO"]
//answer should be NO, but is YES
How can I make it respond with the most recently set value?
You could use the expect methods, e.g.
mockModule = OCMPartialMock(module);
OCMExpect([mockModule send:#"FOO"]).andReturn(YES);
OCMStub([mockModule send:#"FOO"]).andReturn(NO);
That's not exactly what they are meant for, but it does make some sense. You're basically saying, I expect that send: will be called, and when that has actually happened, then I want the method to be stubbed.
Also, if it were possible to "pile up" the stubs, figuring out what went wrong would be quite difficult, e.g. if the first invocation of the stub doesn't happen, then the second invocation will get the value meant for the first.

CPPUTEST: How to ignore only one mocked call placed between other ones

I would like to ignore one call placed between other ones that I want to call under the same case test. If I use ignoreothercalls I have not clear if the rest of the calls, following this, will be called. I need the rest, after ignored call, will be called. Or at least, to find the way of stopping ignoreothercalls effect before the end of the test case.
TEST(group, test1){
...
mock().expectOneCall("HAL_AS393x_CommandStrobes").withParameter("cCommandCode",AS393X_CMD_CALIB_RCO_LC);
/*-------------------------------------------------------*/
mock().expectOneCall("HAL_AS393x_ReadRegisters");//I want ignore only this mocked function call
/*-------------------------------------------------*/
mock().expectOneCall("HAL_AS393x_Deinit");
...
}
I would like to leave this call without being tested, and remove it from de test case without gettig expecting calls errors for it:
mock().xxxCall("HAL_AS393x_ReadRegisters"); //-where xxxCall = unkown keyword used for this-
You have to check expectation in between:
mock().expect...
do_something_that_call_mocks();
mock().checkExpectations();
/* Start all over again */
Complete example using checkExpectations() to reset mock() here

Optional blocks in the middle of a method: safe?

I have a method looking something like:
- (void)doSomething:(void(^)(MyItem *item))optionalBlock {
// 1. Do the regular stuff with the item
item.regularStuff = #"something_regular";
// 2. Run the optional block
// which may or may not make some extra modifications to the item
if (optionalBlock) optionalBlock(item);
// 3. Save the modified item into the Core Data
// etc
}
Which I’m planning to call either like this
[self doSomething:nil];
Or:
[self doSomething:^(MyItem *item) {
// Make some extra modifications to the item before it’s saved
item.custom = #"custom";
}];
Is it safe to assume that at the step three I’ll always get the item already modified by both the method and (potentially) the optional block, or do I need to implement some sort of a way to find out exactly when the block has finished executing so I can continue from there?
It's safe. You don't need any special check.
Yes and no.
Yes, it's safe, in that if the block contains only sequential code for modifying your item, all those modifications will be complete by the time control returns to your doSomething method.
However, if you allow the caller of your method to pass in an arbitrary block, there's no telling what it might do and when. It could set up timers, spawn threads, use dispatch_async, or do any number of other things which could cause it to in some sense not be truly "done" by the time it returns. You're handing over the car keys here -- there's nothing preventing the caller from taking a joyride.
Really, this is the sort of thing that's beyond the scope of the language and more about what sort of contract you define in the documentation of your API: if you want your callers to only modify the object during execution of that block, just tell them that's what you expect them to do and to not expect your API to work otherwise.