How do I verify a method is never called with OCMock 3?
I was thinking something like this:
XCTAssertThrows(OCMVerify([_restDataSource getSomeStuff:[OCMArg any]]));
But it seems like OCMVerify doesn't throw for a fail.
Please see first point under http://ocmock.org/reference/#advanced-topics
Note that reject at this point in time requires the old-style syntax and it must be called before the method may be invoked, ie.
// first set up the mock
[[mock reject] methodThatShouldNotBeCalled]
// then call method that should not result in the call
For a glimpse on what's planned, see https://github.com/erikdoe/ocmock/issues/109
As I answered here, starting from version 3.3 OCMock has OCMReject macro.
I failed miserably at getting the reject-method to work so my solution was to simply stub the method-not-to-be-called(notifyChange: in example below) with throwing an exception whenever it is called.
// Set up the mock.
id<TSModelObserver> observer = OCMProtocolMock(#protocol(TSModelObserver));
// Stub the forbidden method call with throwing an exception.
[OCMStub([observer notifyChange:model]) andThrow:[NSException new]];
Related
I am bridging an objective-c library to React. In order to return the data I need, I have to use a callback. The only problem is, the native method that kicks off the process that generates the data (which is the method that I call from my React js file), is NOT the method that returns the data. In fact, there are quite a few methods between the one that I call, and the final result.
So I have a few options. Either completely rewrite the entire objective-c program (f*ck that), pass the callback function as an argument to every single method and ultimately to the final method where it will be used (this 'works' but is ugly), or a third option which this post is about.
I am new to objective-c (very new) so go easy on me.
Instead of passing the callback function around to every single method, I want to try and make it 'global'. My attempt at doing this looks like
#property(nonatomic,copy)RCTResponseSenderBlock globalCallback;
and the method where it is 'initialized' (which is also the method I call from js)
RCT_EXPORT_METHOD(startScan:(RCTResponseSenderBlock)callback) {
self.globalCallback = callback;
...
}
Now just to test that this works, I added a line of code immediately below the line where I 'initialized' my globalCallback:
RCT_EXPORT_METHOD(startScan:(RCTResponseSenderBlock)callback) {
self.globalCallback = callback;
self.globalCallback(#[[NSNull null], #"Test string"]);
...
}
And it works (as far as I can tell). The callback returns "Test String" to React, and I am able to see it. So I went over to the method where I actually want to return information from and added the same line of code to it (obviously removing the one from the above example):
-(void)theMethodIWantToReturnFrom {
self.globalCallback(#[[NSNull null], #"Test string"]);
...
}
However, this time it does not work. I get EXC_BAD_ACCESS. From what I understand, this may mean that my globalCallback has been deallocated. But whatever it means, I have not been able to figure out a solution yet. Any ideas / explainations regarding this error?
I hope my question is not too basic, as I am new to both obj-c and OCMockito!
I have a void method that I want to stub, so that it does not perform its actions when running a test.
My Method:
-(void)myVoidMethod
{ .. }
I would like to stub it in a way similar to this:
[given([mockDataManager saveChangesToCoreData])];
However if I dont specify a "willReturn" statement I get the following error:
"Argument type 'void' is incomplete"
How can I achieve this in OCMockito?
After getting more details from comments I decide to write the answer here.
IMO partial stubbing (spies) are bad practise. I used it two times in really big legacy project and I would like to change that to something cleaner at some point.
The same opinion is shared between other people. As quick solution you could follow advice from here - subclass and override the method.
Declaring dummy protocol where this method declared as returning id will fix compile error.
#protocol _dummyProtocol
- (id)methodThatReallyReturnVoid;
#end
[[(id<_dummyProtocol>)[mockObject stub] methodThatReallyReturnVoid] andDo:^(NSInvocation *inv){}];
I am trying to use the completion handler on invoke to perform certain actions once the hub has return a result. Im using the following line currently:
myHub invoke:#"stpm" withArgs:messageParam completionHandler:^(SRHubResult *hubResult) {
NSLog(#"Complete");
}
But the block is never called. The invoke still works fine but the block never gets used. Any suggestions as to why?
I can only spot 1.5 issues with your snippet, completionHandler returns either NSDictionary, NSArray, NSNumber, or NSString. Also, is messageParam array?
I have found the issue. In SRHubProxy.m when the method send is called from SRHubProxy.m in invoke, the line:
[_connection send:hubData];
is wrong. The block never gets passed whether you have declared one or not. I changed it to:
[_connection send:hubData completionHandler:block];
which now passes the block correctly and it seems to work.
I've inferred what a lot of things DO in Objective-C, and I've gone through several tutorials that simply talk about the data types, but I haven't run across anything that simply explains the syntax.
For starters, what does this mean? What it does is start a thread and get data returned from a server:
- (void)apiCall:(void (^)(NSMutableArray *list))block {
Does something in that function header tell me that it is asynchronous? is that what block means?
No, block doesn't mean asynchronous, a block in Obj-C is just a bit of code that can be passed as an argument to a method.
methods that start with - are instance methods and those that start with + are class methods.
^ is a syntactic marker to denote a block.
For your first question: you would have to look at the API documentation to find out if it is asynchronous.
For more information about blocks in general, see here:
Apple Blocks Programming Guide
Let's start with your second bullet:
Class methods are declared with +, instance methods are declared with -.
The first and third are related, the parameter named block is a code block, it's a piece of code intended to be run later. Given the name of this method apiCall, I suggest this being the method run after the call is done.
It would we natural to suspect that this method will do some work on another thread and then invoke the block you supplied, but for this you'd need to check the documentation or the code.
The signature: (void (^)(NSMutableArray* list)) block describes a code block with a void return type and a NSMutableArray* list as only parameter.
An example usage of the block parameter would be:
void (^apiCallCallback)(NSMutableArray*) = ^(NSMutableArray* list) {
NSLog(#"The API returned %d items in a list", [list length]);
}
[someApiInstance apiCall:apiCallCallback];
After the API instance is done doing whatever it is suppose to do, you'll see that the log statement is printed.
In the below method calls from a single object, how to make the handler method to run 1st and then the main method in Objective-C?
Does it run in Asynchonous or Synchronous way?
Main method :AuthenticateMobileServer
handler Method :Handler
[mobile_Obj authenticateMobileServer:self action:#selector(handler:)];
Thank You.
I'm not sure if I'm getting what you're asking. But first of all please do use correct naming/capitalization for Objective-C! So please take a look at (http://developer.apple.com/mac/library/documentation/cocoa/conceptual/objectivec/articles/ocLanguageSummary.html)
(method names and variable names are in lowerCamelCase! Only class names are in CamelCase)
so it should be [mobileObj authenticateMobileServer:self action:#selector(handler:)]
Now to your question. By sending a authenticateMobileServer:action: message to mobileObj only that method is executed. #selector(handler:) is only a function pointer.