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.
Related
Situation
For a project of mine, I'm building some kind of extension. This extension must have a class that implements a method whose declaration is - (id)initWithBundle:(NSBundle *)bundle.
Issue
My extension has multiple classes, but the host app is so badly written that it calls - (id)initWithBundle:(NSBundle *)bundle on different classes, randomly.
I'm not willing to reduce the number of classes, so the only solution left would be to somehow forward to caller to the class that actually implement - (id)initWithBundle:(NSBundle *)bundle (A bit like a HTTP 302). I found many resources on forwarding calls, but not such thing as forwarding an -init method...
init is allowed to return an object other than itself. While I highly recommend fixing the calling code (I can't imagine a case where allowing for code that calls anything "randomly" is even a reasonable idea), if you want to return some other object from init, it works like this:
- (id)initWithBundle:(NSBundle *)bundle {
// I don't actually implement this, let's return the class that does
return [[OtherClass alloc] initWithBundle: bundle];
}
ARC will deal with throwing you away.
The caller now has the wrong type of course (they expect your type, and they have some other random object), which is very likely to lead to hijinks, very hard to track bugs, and general sorrow. But it's legal ObjC. And if the two classes have enough overlap of their methods, it might even work.
In normal cases, this pattern is called a Class Cluster. See What exactly is a so called "Class Cluster" in Objective-C? for some examples.
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.
Say I have a method like this I want to test and it uses class methods:
#implementation User
...
- (void)methodToTest
{
NSString *retval = [UserResourceTable staticMethod];
// do something here
}
#end
Since UserResourceTable is not injected and it is a message to a class and not a instance, it doesn't look to me like it is amenable to mocking. I don't want the real method to execute, as it incurs network access.
Similar question is asked for C#. Jay says "This is one of the reasons that using statics in this way is sometimes frowned upon", though isn't that just the way with class methods and plenty of Apple's own libraries use it?
The advices given are to wrap it in an adapter so it can be messaged to an object instance instead and to inject it in the constructor.
Say I wrapped it like this:
#implementation UserResourceWrapper
- (NSString *)staticMethodWrapper
{
return [UserResourceTable staticMethod];
}
#end
I am not so fond of the injection part. I think I do not want it to be exposed externally. So I still end up subclassing the User class and create a factory method to return, and have methodToTest calls it
#implementation User
- (NSString *)urt
{
return [UserResourceTableWrapper new];
}
- (void)methodToTest
{
NSString *retval = [[self urt] staticMethod];
// do something here
}
#end
In unit test, I would subclass the class I want to test which is User and override that urt: method. That looks like a lot of work. Another possible method I can think of is to swizzle [UserResourceTable staticMethod]. This looks like a lot of trouble for the job. Risking for being marked as not in a good FAQ format blah blah so infamous on StackOverFlow (wink), what's the standard practice here? Is there a ready-made library to swizzle? It doesn't look like OCMock or OCMockito can do this, they appear to be able to be used only when injected.
EDIT:
I'm getting the feeling that injection is the best possible way. With subclassing + factory method, if I want to provide different behaviors for different test cases (success case & failure case, for example). I would need two mock classes each providing a different behavior. That's a lot of boiler plates for a few tests. With swizzle, once you swap it you swap it for good and it takes effect in all the tests. However if I can inject it, the mock can be created right within the unit-testing method and seems easy-peasy.
What you want to do is inject UserResourceTableWrapper. Here's an example using setter injection using a property:
#property (nonatomic, strong) Class userResourceTableWrapperClass;
Then instead of directly calling
[UserResourceTableWrapper staticMethod]
you'd call
[self.userResourceTableWrapperClass staticMethod]
You can accomplish this using the various forms of dependency injection:
Property injection (shown above)
Constructor injection (that is, through initializer argument)
Method argument injection (if use has limited scope)
Extract and Override is another possibility, but I try to limit it to legacy code.
While recently working with Objective-C and various libraries written in it, I've noticed two really popular singleton patterns. One version fetches the singleton instance and calls its instance methods and other version only exposes class methods and never gives you an instance to work with. All have the purpose of abstracting access to a single resource (StoreKit, CoreData, Parse API etc.). For example, here's the former approach used in MKStoreKit:
// initialize singleton during app boot
[MKStoreManager sharedManager]
// sometime later in the app
[[MKStoreManager sharedManager] buyFeature:kFeatureAId
onComplete:^(NSString* purchasedFeature)
{
NSLog(#"Purchased: %#", purchasedFeature);
}
onCancelled:^
{
NSLog(#"User Cancelled Transaction");
}];
or alternatively NSUserDefaults, UIApplication etc.. The other approach can be seen in MagicalRecord or here with Parse API:
// configure API credentials sometime during app boot
[Parse setApplicationId:#"123456"
clientKey:#"123456"];
// sometime later
PFObject *testObject = [PFObject objectWithClassName:#"TestObject"];
[testObject setObject:#"bar" forKey:#"foo"];
[testObject save];
What are some pros and cons of the two approaches and is one of them fundamentally better than the other?
Not having to retrieve the shared instance saves some screen estate (the performance difference is likely irrelevant), but am I screwing myself in some other way, for example, testability-wise?
Thanks!
There are two different ways to implement the approach based on class methods:
Make a singleton instance using a class hidden from everybody, and hide its methods behind wrapper class methods with identical signatures, or
Make class methods that do all the work
The implications of the first implementation are that everything you can do with a singleton, you can do with the hidden singleton:
using a subclass becomes a possibility
switching the instance in the middle of the run is easy
the state lives in instance variables
initialization follows the familiar pattern
If you go for an implementation that does not use a singleton, you would be relying on static variables to keep your current state. That is a legitimate choice, but the initialization pattern becomes different (perhaps even using a dispatch_once), you cannot switch the implementation in the middle without relying on some ugly if conditions, and using a subclass becomes a lot more tricky.
Testing the first implementation is somewhat easier than testing the second one, because you can provide a separate implementation of the singleton for testing, perhaps through the back door; with a static-based implementation, this route cannot be taken.
To summarize, I would use a singleton-based solution, with the singleton optionally hidden behind a "facade" that provides access to singleton's methods. I would not use an implementation where all state must be placed in static variables.
One advantage of the singleton approach is that it becomes trivial to allow other instances if you need to. If you take the class method approach, that's all you get without a lot of refactoring.
I've been in many situations where my core logic is in private methods.
How would you go about unit testing that, is there any kind of compile time manipulation to ignore compile errors for unknown/private methods? I know that for the second part of the code I could use performSelector, but is that a reasonable solution?
For instance:
[[self.objectMock expect] privateMethod];
or
[self.object callPrivateMethodsToExpectSomeOtherBehaviour]
EDIT:
Here is an example to demonstrate why I feel like I need to test some private methods.
Are these tests not reasonable? How else would I test that calling clear actually does what it suppose to do?
- (void)clear
{
self.orderNumber = nil;
[self.items removeAllObjects];
// Clear the rest of fields
}
- (void)testClearShouldRemoveOrderNumber
{
Order *order = [[Order alloc] init];
OCMockObject *orderPartialMock = [OCmockObject partialMockForObject:order];
[[orderPartialMock.items expect] setOrderNumber:nil];
[orderPartialMock clear];
[orderPartialMock verify];
}
- (void)testClearShouldRemoveItems
{
Order *order = [[Order alloc] init];
order.items = [[OCMockObject niceMockForClass:[NSMutableArray class]];
[[orderPartialMock.items expect] removeAllObjects];
[orderPartialMock performSelector#selector(clear)];
[orderPartialMock.items verify];
}
Methods are never "private" in the sense that once a class implements a method, it can be sent my anyone.
So, let's say you have a class Foo with a "private" method bar that is not in the interface declaration. You could, from anywhere, still invoke bar though you may get a compiler diagnostic.
Probably the simplest approach is to declare the methods in a category that your tests use. For example:
#interface Foo (MyPrivateMethodsUsedForTesting)
- (void)bar;
#end
Now, you can use them without the compiler complaining either. Note, the methods do not have to be implemented in an actual MyPrivateMethodsUsedForTesting category. This technique is also sometimes referred to as an "informal protocol."
EDIT
Also, as noted by others, that if you need to access private methods, you probably should revisit your design. After ~30 years doing this, there are definitely times where, especially for tests, you need to access private stuff, but most times it means some type of design review is in order.
You should not test your private methods directly. Instead, you need to test them through the public methods. Here is a link to a question on programmers.stackexchange.com discussing the matter.
The general idea of the answers is that you (or anyone else maintaining your code) should be free to change your private methods at any time by altering the signature, changing implementation, or removing them altogether. Nobody outside your class should care - after all, that's the primary driver behind making these methods private in the first place.
If you change your private method in an incompatible way, then unit tests of your public methods must break; otherwise, you didn't do a good job of testing your public methods. Effectively, this renders unit testing of private methods unnecessary.
In general you shouldn't need to unit test private methods.
The publicly exposed methods tell you what your class does - this is what you care about, and you should test these. The private methods are concerned with how your class does its job, your test shouldn't care about how the job gets done, as long as it gets done correctly.
If one day you decide to change how your class does its job (i.e. by changing the code in your private methods), without changing what your class actually does, then your unit tests should continue to pass. By trying to test the internals of your class you create a brittle test which may break even though the class is still working correctly.
If you are finding it difficult to test your class thoroughly by just using public methods then this is a warning sign that your class may be too big - consider breaking it up into smaller pieces.
You do not need to unit test these - in fact you should not.
You will test your privat method indirectly via you public methods. Private methods are helper methods to get the job done for your public methods.
Since you should be free enough to change your private methods as you like unit tests would be counter productive too.
But be sure to test all the cases for your public methods so that all you private methods are covered.