As I heard before and recently learned in Jon Reid’s very good screencast, some init methods or in iOS applications, the viewDidLoad methods tend to get bigger and bigger. I tried to refactor this method:
- (void)viewDidLoad {
// 10+ lines of setting default property
// 20+ lines of setting up the navigation bar
// 20+ lines of resetting the view hierarchy
}
This was replaced by a very nice and short method that contains calls to other methods with speaking names:
- (void)viewDidLoad {
[super viewDidLoad];
[self setDefaultResourceNames];
[self setupRightBarButtonItems];
[self restoreNavigationControllerHierarchy];
[[NSNotificationCenter defaultCenter] addObserver: (...)];
}
Now those three methods are now being unit tested, which is much better than before. Now my question is, should the viewDidLoad method be tested as well?
To do this, I made a partial mock out of my class under test and wrote the following test:
- (void)testViewDidLoadShouldInstantiateControllerCorrectly {
NewsItemDetailsViewController *sut = [[NewsItemDetailsViewController alloc] init];
id mockSut = [OCMockObject partialMockForObject:sut];
[[mockSut expect] setDefaultResourceNames];
[[mockSut expect] setupRightBarButtonItems];
[[mockSut expect] restoreNavigationControllerHierarchy];
[mockSut viewDidLoad];
[mockSut verify];
}
Is this any good? This seems to be largely coupled to actual source code and method execution rather than effects caused by calling the method (which is actually what unit testing is about, as far as I learned). But the effects of calling the method are actually covered in the three unit tests, testing the sub-methods.
Is it good to have this test or is it unnecessary when all other calls are already under test?
This is a perfectly reasonable approach. You want to test two types of things: 1) things you don’t want to break, and 2) things you want to document. If this approach fits either or both of those criteria for you it’s fine.
I think the main drawback of tests like this is that they can add a lot of coding overhead to something that is self-evident. View setup code is often very readable–you can scan through it and understand what’s going on, so the tests don’t add much documentation value. And if the view is one you use every time you use the app, it may be immediately clear when you do QA if any of the view setup is broken, so the tests don’t add much defensive coding value.
In the end, you’re the one who will maintain this code and be responsible for fixing it when it breaks, so it’s up to you to determine whether the testing effort now outweighs the risks later.