Using partialMockForObject to do singleton class mock, how to create a method like "removeAllExpectations” to remove all remembered ones? - singleton

Confused on OCMock for singleton, get two methods, but none of them is perfect in my opinion.
Using partialMockForObject.
I want to use partialMockForObject to do singleton class mock. See following code, it works well, but the defect is that singleton [NSNotificationCenter defaultCenter] will remember previous mock behavior, then when invoked in another place, it will crash, unexpected. So my question is that how can I create a method like "removeAllExpectations” to remove all remembered ones?
id aMock = [OCMockObject partialMockForObject:[NSNotificationCenter defaultCenter]];
[aMock expect] removeObserver:[OCMConstraint isKindOfClass:[WhereIsMyPhoneViewController class]]];
[[aMock verify];
Using category method. See http://twobitlabs.com/2011/02/mocking-singletons-with-ocmock/ mentions another method to do singleton mock, personally I prefer partialMockForObject, you don't need to mock all methods when unit testing.
Have sent my question to OCMock development group but no response got yet, need your smart guys opinion. Any idea or discussion will be appreciated, thanks in advance.

If you are using the lastest source code of OCMock (after
2012-04-06), call
[aMock stopMocking];
to reset the mocked object's state.

You can call:
[aMock stop];
to reset the mocked object's state.

Related

Using OCMock to mock an internal object and change the behavior of a instance selector

I'm trying to use OCMock to modify the behavior of an instance selector for a specific class where I don't have a direct pointer to the instance of the class in question.
I've found a few posts online that claim to allow doing at least part of this, for example: How to mock an object with OCMock which isn't passed as a parameter to method?
I tried following the guidance in one of the answers in that post, specifically relying on code like this:
id mockController = OCMClassMock([WebAuthViewController class]);
OCMStub([mockController alloc]).andReturn(mockController);
OCMStub([mockController initWithAuthenticationToken:OCMOCK_ANY authConfig:OCMOCK_ANY]).andReturn(mockController);
However, I am having difficulty understanding this code. First of all, where does the actual "alloc" logic run? The code seems to be saying "mock alloc and return an existing class method", but alloc is supposed to return an instance, not a class. Is this some magic build into OCMock?
Also, on a related matter it seems the init is simply returning the same mocked class, not an instance of that class. It seems really strange that this returns the same thing as the previous mock, and I don't understand where the actual custom init logic is being called. It seems to be omitted completely since there is no call to .andForwardToRealObject() anywhere.
However, ultimately my main problem is I don't understand how to mock an instance method using the above code since things are working on class, not an instance. I tried to write a similar mock to modify the behavior of an instance method (using the equivalent of mockController above), but it said the method was not there.
I tried a bunch of things, but could not get OCMock to handle this case. If anyone can point me to an example that mocks a specific instance method for all instances of a class, I'd appreciate it.
By the way, I was able to get things working by using swizzling without any use of OCMock, but it seems really hacky (especially when I'm using OCMock for everything else), so I would love to get this working with OCMock.

How can I verify method calls to an NSURLProtocol mock using OCMock or OCMockito?

I would like to test a method which makes a GET request.
Here's a contrived example:
- (void)GET:(NSString *)URLString;
Rather than worry about the implementation details of this method (e.g. mocking, setting expectations, and then verifying a dependency), I'd prefer to just be able to test if the GET request was made.
I believe I can do this with NSURLProtocol but my attempts so far have been unsuccessful.
For example, using OCMock:
id mockURLProtocol = (NSURLProtocol *)[OCMockObject mockForClass:[NSURLProtocol class]];
[NSURLProtocol registerClass:mockURLProtocol];
[[mockURLProtocol expect] canInitWithRequest:[OCMArg any]];
[MYClass GET:#"test"];
[mockURLProtocol verify];
[mockURLProtocol stopMocking];
[NSURLProtocol unregisterClass:mockURLProtocol];
The above test fails since canInitWithRequest is never called.
How can I set expectations on NSURLProtocol to verify that the request is being made?
Mocking NSURLProtocol doesn't make sense to me. NSURLProtocol is used in testing to create canned responses to certain requests, there is no need of mocking it (you don't want to test how the system interacts with it). This project makes use of NSURLProtocol, it may be useful for you in case you want to use this approach instead of a pure unit test where you test your NSURLConnectionDelegate implementation directly.

Method Swizzling - How to assure methods are swizzled before they are called

I'm method swizzling a third party applications creation of NSMenuItems with SIMBL, but 50/50 of the time the menu-items are created before my method swizzling is initialized.
What is a clean way to make sure my swizzling always comes first? I guess I could swizzle applicationDidFinishLaunching: and continue my swizzling there. But I'm afraid I'm going to run in to the same error there, where applicationDidFinishLaunching will be called before my actual swizzle is in place.
John
You'd want the swizzle to happen as soon as the libraries are loaded. You can do that via +initialize, +load, or a constructor function.
#bbum's answer to this question has a bit more information, along with one of his blog posts on the caveats of using these special class methods.
(And I'm purposely not questioning the wisdom of what you're doing ;) )
You can use constructor functions like this:
__attribute__((constructor)) static void do_the_swizzles()
{
// Do all your swizzling here.
}
From GCC documentation:
The constructor attribute causes the function to be called
automatically before execution enters main().
Note: Although this is originally from GCC, it also works in LLVM.

Make NSInvocation invoke a specific IMP

I'm looking for a way to make an NSInvocation invoke a specific IMP. By default, it invokes the "lowest" IMP it can find (ie, the most-recently-overridden version), but I'm looking for a way to make it invoke an IMP from higher up in the inheritance chain. The IMP I want to invoke is determined dynamically, or else I'd be able to use the super keyword or something like that.
My thought was to use the -forwardInvocation: mechanism to capture a message (easy and already working) and then alter the IMP so it goes to a method that is neither the super implementation nor the furthest descendent's implementation. (hard)
The only thing I've found that comes remotely close is AspectObjectiveC, but that requires libffi, which makes it non-iOS compatible. Ideally I'd like this to be cross platform.
Any ideas?
disclaimer: i'm just experimenting
Trying out #bbum's idea of a trampoline function
So I think I've got things mostly set up; I've got the following trampoline that gets correctly added via class_addMethod(), and it does get entered:
id dd_trampolineFunction(id self, SEL _cmd, ...) {
IMP imp = [self retrieveTheProperIMP];
self = [self retrieveTheProperSelfObject];
asm(
"jmp %0\n"
:
: "r" (imp)
);
return nil; //to shut up the compiler
}
I've verified that both the proper self and the proper IMP are the right things prior to the JMP, and the _cmd parameter is also coming in properly. (in other words, I correctly added this method).
However, something is going on. I sometimes find myself jumping to a method (usually not the right one) with a nil self and _cmd. Other times I'll just crash in the middle of nowhere with an EXC_BAD_ACCESS. Ideas? (it's been a long time since I've done anything in assembly...) I'm testing this on x86_64.
NSInvocation is just an object representation of a message send. As such, it can't invoke a specific IMP any more than a normal message send could. In order to have an invocation call a specific IMP, you'd either need to write a custom NSInvocation class that goes through the IMP-calling routine or you'd have to write a trampoline that implements the behavior and then create an invocation that represents a message to the trampoline (i.e. you basically wouldn't be using NSInvocation for much of anything).
Added long after the fact, for reference:
You can do it with private API. Put this category somewhere convenient:
#interface NSInvocation (naughty)
-(void)invokeUsingIMP:(IMP)imp;
#end
and voila, it does exactly what you'd expect. I dug up this gem from one of Mike Ash's old blog posts.
Private API tricks like this are great for research or in-house code. Just remember to excise it from your appstore-bound builds.
Given that you already have the IMP, you simply need a way to do a very raw forward of the method call to said IMP. And given that you are willing to use an NSInvocation like solution, then you could also build a similar proxy class.
If I were faced with this, I would create a simple proxying class that contained the IMP to be called and the target object (you'll need to set the self parameter). Then, I would write a trampoline function in assembly that takes the first argument, assumes it is an instance of the proxying class, grabs the self, stuffs it into the register holding argument 0, grabs the IMP and *JMPs to it as a tail call.
With trampoline in hand, you would then add that trampoline as an IMP for any selector on the proxying class that you want forwarded to a particular IMP....
To achieve any kind of generic mechanism like this, the key is to avoid anything having to do with rewriting the stack frame. Avoid the C ABI. Avoid moving arguments about.
An untested idea:
Could you use object_setClass() to force the selection of the IMP that you want? That is…
- (void)forwardInvocation:(NSInvocation *)invocation {
id target = [invocation target];
Class targetClass = classWithTheImpIWant();
Class originalClass = objc_setClass(target, targetClass);
[invocation invoke];
objc_setClass(target, originalClass);
}
I think your best choice is to use libffi. Have you seen the port to iOS at https://github.com/landonf/libffi-ios? I haven't tried the port, but i have successfully invoked IMP with arbitrary arguments on the Mac.
Have a look at JSCocoa https://github.com/parmanoir/jscocoa it includes code to help you prepare a ffi_cif structure from a Method and it also contains a version of libffi that should compile on iOS. (Haven't tested either)
You should probably have a look at how we swizzle the implementation of a certain method on an instance of an object in https://github.com/tuenti/TMInstanceMethodSwizzler
Basically, you swizzle the method for all object of a class so when its called it look up in a dictionary whats is the implementation which has to be called for the target object, falling back to the original implementation if not found.
You can also use the private invokeWithImp: method, but this is discouraged if you intent to submit the app to the store.
you could add the IMP to the class using class_addMethod under a new selector and invoke that selector.
the temporary method can't be removed though.

Unit testing with NSURLConnection

I want to test a piece of code that uses network (the NSURLConnection class, to be specific). The code (let’s call it NetworkManager) looks a bit like this:
- (id) buildConnection
{
// some more code and then:
return [NSURLConnection …];
}
- (void) startNetworkSync
{
id connection = [self buildConnection];
//…
}
In the unit test I would like to get rid of the networking, ie. replace the NSURLConnection object by a mock. How do I do this?
I’ve tried creating a partial mock of the NetworkManager that would replace the buildConnection method by a stub. The problem is that partial mocks as done by OCMock only stub messages from the outside world – sending buildConnection from the startNetworkSync invokes the original method, not the stub.
I have also tried monkey-patching the NetworkManager class through a category. This works, I can easily override the buildConnection method by other code and replace the real NSURLConnection with a stub. The problem is that I found no simple way I could get the stubbed connection in the test – the connection is a private part of the NetworkManager.
Then I could subclass the NetworkManager, override the buildConnection method and add an instance variable plus an accessor for the created connection. This seems like a lot of code, though.
How would you solve this? I am looking for a solution that keeps the NetworkManager class design clean and does not require much magic nor much code in the test.
This is the kind of thing dependency injection is designed to solve; if you use startNetworkSyncWithConnection:(NSURLConnection*) instead you can easily test the method with a mock connection. If you don't want to change the API for your clients you could even keep startNetworkSync as a wrapper that does nothing but call that new method with [self buildConnection] as the argument.
I modified OCMock to support real partial mocks, see the repo on GitHub.
Another solution I have used recently is to completely abstract the networking interface. If the class needs some data from the network, it probably interacts with some server service that can be explictly modelled as a protocol:
#protocol SomeNetworkService
- (NSArray*) allAvailableFoos;
- (void) insertNewFoo: (Foo*) foo;
#end
And then you’ll have a real HTTP implementation and a testing one. This means more work, but also much better testability. The tests are less brittle and much more convenient, since the testing network layer can do whatever you need.