Unit testing view controllers

Dec 10, 2012 17:26 · 254 words · 2 minute read

View controllers have a reputation as being tricky to test. This isn’t necessarily the case - this is another outboard-brain post, so I remember how to do this:

The scenario

You want to test - for example - that your view controllers are doing whatever they need to do when loaded. In other words, does the viewDidLoad method do what it should? Note that this is distinct from testing from a UI perspective - what I’m talking about here is unit testing the controller, rather than the interface.

The approach

Start by refactoring out the functionality of the viewDidLoad method into separate standalone methods. For example, if the view controller runs some kind of data fetch, then move this functionality into its own method - say -(void)fetchData;

Then you can test two things - firstly testing that the methods do what they’re supposed to, by testing that method in isolation (or more accurately, writing the test then writing the method…)

Secondly, it becomes possible to easily test that the view controller’s lifecycle methods are doing what they should. This is a bit more involved, and needs the methods under test to be stubbed out. This Kiwi test verifies that the view controller calls fetchData as part of viewDidLoad:

MyViewController *testController = [[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil];
[testController stub:@selector(fetchData)];
[[[testController should] receive] fetchData];
[testController viewDidLoad];

This will test that your testController’s viewDidLoad method looks like this:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    [self fetchData];