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.
Related
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.
I've started using Xcode's refactoring abilities (edit > refactor > extract) and noticed that Xcode offers to extract a method or a function.
I've read here and elsewhere about the differences between the two and understand that a method is connected to a class while a function is not. So I'm not looking for definitions, please.
Assuming that no arguments are involved, when is it appropriate to use one instead of the other? I understand that if something isn't really about the class then it could be a function but again, that's just about the definitions. I'm looking for good ol' use cases.
In my personal case, I'm trying to refactor some code out of the AppDelegate's applicationDidEnterBackground. As it is the only place to handle events upon entering the background, the only way to clean up the code is to extract subroutines into .. well, functions. But they'd be inside AppDelegate.m so wouldn't they be methods?
Hmmm..
Personally, I only use functions if, and only if, the following two requirements are met:
I use it so frequently within a given class, or throughout the project, that it warrants being generalized.
It has no side-effects or context dependancies (none of that void *context mess).
In my opinion, C-style functions should only be used as a last resort or in cases where you truly need functional behavior within this kind of an application. Event handling is both application-specific, and context sensitive, so it's best if you left that alone and focused on refactoring common patterns out.
You use functions when you have a, well, function ;-) You know the definitions: a method has an implicit argument self and can access instance variables using that; a function has no implicit arguments - everything it needs must be passed in.
If you are refactoring part of a larger method, that part does not access instance variables, and you are not refactoring it so that a subclass can override it, then let Xcode build you a function. When its done add static to it so it is private to the class.
In doing this you've lost nothing and made it clear that the piece of code is a function - it does not alter the state of the object.
There is of course no hard line between picking a function and a method, its a fuzzy boundary. If a piece of code, say, just accesses one or two instance variables but does not update them then you might pick a function - again making it clear that the object state is not being modified. But you don't want to pass lots of instance variables in as parameters, that is just hard to read (and inefficient).
Using functions can be good, and its certainly not bad to do so in Objective-C.
Method of a class usually need to access instance variables connected to that class. Functions in Objective-C are not connected to a class, and therefore have no access to any non-public member variables of classes.
Consider the class KNode, which contains member variable _memberVar.
#interface KNode : NSObject {
int _memberVar;
}
#end
Any method of this class could access and change the member variable, but any old function cannot, as it is private.
#implementation KNode
- (void)modify {
_memberVar = 10;
}
#end
The following function will not work
void modify(KNode * node) {
_memberVar = 10;
}
Two small but meaningful advantages of functions:
They can be internal-only by marking them static, or
__attribute__((visibility("hidden"))), which is helpful for framework developers
They can be inlined. For example, I use this pattern for fast lazy queue creation:
static inline dispatch_queue_t sharedQueue() {
static dispatch_queue_t queue;
static dispatch_once_t once;
dispatch_once(&once, ^{
queue = dispatch_queue_create("foo", 0);
});
return queue;
}
OK, I know this question might seem irrelevant or too basic, but - since I always want to know what I'm doing and why I'm doing it, if it fits my design - please shed some light.
So, here's what I need :
Let's say we've got a class
We want to use its methods from pretty much anywhere
Instead of passing an object around, I decided to go for class methods and pseudo-global instances
So, let's say we've got a class named "MyDocumentManager".
This is what I usually do :
+ (MyDocumentManager*)documentManager
{
MyDocumentManager* newDocumentManager = [[MyDocumentManager alloc] init];
if (newDocumentManager)
{
// initialize that new document manager
}
return newDocumentManager;
}
And then use it like :
[[MyDocumentManager documentManager] someMethod];
However, I usually see people suggesting something like :
+ (MyDocumentManager*)sharedManager
{
static dispatch_once_t pred;
static MyDocumentManager *sharedManager;
dispatch_once(&pred, ^{
sharedManager = [[MyDocumentManager alloc] init];
});
return sharedManager;
}
So, here's my questions :
Is is the same thing?
If not, what is the difference?
What are the pros/cons of its approach? (in terms of memory/speed/etc)
Which one should I use and why?
Do they both fit what I need them for?
Is it the same thing?
No.
If not, what is the difference?
What you have doesn't implement a singleton, since it allocates a new instance of the class upon every function call. It's rather called a factory method. The definition of a singleton is that a certain class method always returns the same instance of the class.
Which one should I use and why?
You should generally avoid using singletons, because it's often considered bad practice, although there are cases when it's handy to have them. For example, if you have a class that uses encapsulated data but you only need quasi class-level methods, then it's better to implement a singleton with properly placed instance variables than implement class methods and tons of global/static variables (this is because in Objective-C, classes can't have member variables, only objects).
Do they both fit what I need them for?
You decide that.
The code you pasted in "what I usually do" is broken. It doesn't return a singleton. It returns a brand new object every time you call it (and if this isn't ARC then it's leaking it too).
The code you pasted as what people suggest is the correct code. Not only does it return a shared object each time, without leaking, but it's also thread-safe (so far as initialization of the object is concerned; it doesn't say anything about whether use of the object is thread-safe).
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.
I have a singleton class, and can't unit test their code.
I have test like:
Db *db = [[Db alloc] initWithName:#"sample.db"];
[db createDb];
STAssertEquals([db existDb],YES,#"The db is not created!");
But only work the first. When the second is executed, I always get "null" from the initWithName method. When I remove the singleton support code, all work as expected.
I could hack the testing (but I don't know how right now) but wonder if exist a "poper" way to deal with this.
The singleton is located here: http://code.google.com/p/chibiorm/source/browse/trunk/src/Db.m
Singletons are hard to unit test and are sometimes the result of poor design.
My recommendation would be to think hard about whether you really need a singleton in the first place.
Maybe you could use the Factory pattern and create a factory that hands out only one instance (effectively your singleton). Then the implementation is not a singleton and you can unit test it to your hearts content.
The only drawback is that you are not protected by the language to create your own instance if you don't retrieve it from the factory. In C++ you may overcome this by making the constructor private and the factory and the unit test friends. I am not sure if Objective-C has a similar feature.
I think you shouldn't return nil on the second alloc but raise an exception. If you want to use a singleton you should not try to create two :).
However, if I decide to create a singleton my class looks like:
#implementation MySingleton
static id _instance = nil;
+ instance
{
if (_instance == nil) {
// alloc/init
_instance = [[self alloc] init];
…
}
return _instance;
}
…
#end
As you can see I am not enforcing that there may never be more than one instance. Instead I am using the convention to get the instance only with the instance method.
The guy here has written what I would have written as the answer, which is use categories to provide differnet instances from your singleton methods as needed.
http://twobitlabs.com/2011/02/mocking-singletons-with-ocmock/
The other guys above who are all pontificating their opinions of "singletons are bad m'kay" should be ignored. The first thing I did when I switched to objective c was write an iOC library, which I never used because I realised that objective c is NOT java, so please ignore people who bleet on about about java dogma : it doens't always apply to objective c.