I'm using RestKit in my application, setting it up in the AppDelegate. I have some unit tests that depend on the RKObjectManager
singleton. This is set up in the AppDelegate. Some tests set up a managed object store specifically for the tests, as below. Others call getObject
etc on it directly to test response mappings.
This is in my test setUp
:
RKObjectManager *mgr = [RKObjectManager sharedManager];
[mgr setManagedObjectStore:managedObjectStore];
This has been working successfully for a long time.
I recently updated my Cocoapods gem from 0.33.1
to the latest (0.38.2
right now), and now, in the above example mgr
is nil
. If I drop a breakpoint on the second line above, the sharedManager
clearly returns a non-nil value, yet my local variable is nil:
(lldb) po mgr
nil
(lldb) po [RKObjectManager sharedManager]
<RKObjectManager: 0x7fe9e2d1d5e0>
I suspect I have, effectively, two copies of RKObjectManager
loaded at runtime (once from the app bundle and once from the test bundle). I've tried all the solutions listed here, but the comment of interest talks about how each target gets its own copy of the class. Indeed, if I override the +(void) load
method on RKObjectManager
, it gets called twice.
If I store a reference to the shared manager as a property on my AppDelegate, then I can retrieve the shared instance from that successfully - just not from the class method as above. I'd rather not repeat this work-around across all my tests.
How can I configure Cocoapods to link the "right" version of RKObjectManager with my tests, so I can retrieve the shared instance directly once more?
My podfile:
platform :ios, '8.0'
target 'Closeout' do
pod 'RestKit'
... some other pods
end
target 'CloseoutTests' do
pod 'RestKit/Testing'
pod 'OHHTTPStubs'
end
Edit: I have a workaround that's certainly better than exposing a property on the AppDelegate simply for the benefit of testing, but I'd still like to know how to avoid doing this:
AppDelegate* delegate = (AppDelegate*)([UIApplication sharedApplication].delegate);
NSBundle *appBundle = [NSBundle bundleForClass:[delegate class]];
id objMgr = [appBundle classNamed:@"RKObjectManager"];
[[objMgr sharedManager] setManagedObjectStore:managedObjectStore];
CocoaPods changed the way dependencies are added in version 0.36 - the release blog has a very good explanation of why this is necessary, but the general idea is that it was required for Swift support.
I added the following keyword, introduced in CocoaPods 0.36 to my Podfile:
use_frameworks!
I removed my targets and used link_with
instead, so my Podfile looks like this:
platform :ios, '8.0'
link_with 'Closeout', 'CloseoutTests'
use_frameworks!
pod 'RestKit'
pod 'RestKit/Testing'
pod 'OHHTTPStubs'
... other pods
Additionally, I had to ensure I was running RestKit 0.25 or higher, as that includes this PR, enabling support for Frameworks.
pod 'RestKit', '0.25.0'
Finally, I had to fix a bunch of compilation errors:
#import <RestKit.h>
became #import <RestKit/RestKit.h>