ios - How to unit test a UIViewController - TDD/BDD -
unit testing never seem able head around can see why important , can huge time saver (if know you're doing). hoping can point me in right direction.
i have following uiviewcontroller
qbelectricitybasevc.h
@interface qbelectricitybasevc : qbstatevc  @property (nonatomic, strong) qbelectricityusage *electricityusage; @property (nonatomic, assign) cgfloat tabbarheight;  - (void)updateelectricityusage;  @end   qbelectricitybasevc.m
@implementation qbelectricitybasevc  - (instancetype)init {     self = [super init];     if (self) {         self.tabbaritem = [[uitabbaritem alloc] initwithtitle:nslocalizedstring(@"electricity_title", nil) image:nil tag:0];     }     return self; }  - (void)viewwillappear:(bool)animated {     [super viewwillappear:animated];      [self.notificationcenter addobserver:self selector:@selector(updateelectricityusage)                                                  name:kupdatedelectricityusagekey object:nil]; }  - (void)viewwilldisappear:(bool)animated {     [super viewwilldisappear:animated];      [self.notificationcenter removeobserver:self]; }  - (void)updateelectricityusage {     self.electricityusage = [self.statemanager electricityusage]; }  - (cgfloat)tabbarheight {     return self.tabbarcontroller.tabbar.frame.size.height; }  @end   what should test?
- an observer 
kupdatedelectricityusagekeyadded self.electricityusagebecomes instance ofqbelectricityusage- a 
tabbarheightreturned - an observer 
kupdatedelectricityusagekeyremoved 
am missing should test or testing shouldn't?
how test?
so trying using specta , expexta. if need mock using ocmockito.
i don't know how test observer added/removed. see following in expexta documentation not sure if relevant/how use it:
expect(^{ /* code */ }).to.notify(@"notificationname"); passes if given block of code generates nsnotification named notificationname.  expect(^{ /* code */ }).to.notify(notification); passes if given block of code generates nsnotification equal passed notification.   to test self.electricityusage becomes instance of qbelectricityusage create category has method pretends notification fired , calls updateelectricityusage method best way?
and tabbarheight, should test returns valid cgfloat , not worry value is?
update
i changed viewwillappear method below:
- (void)viewwillappear:(bool)animated {     [super viewwillappear:animated];     [self addnotificationobservers]; }  - (void)addnotificationobservers {     [self.notificationcenter addobserver:self selector:@selector(updateelectricityusage)                                     name:kupdatedelectricityusagekey object:nil]; }   and created following test:
#import "specs.h"  #import "qbelectricitybasevc.h" #import "electricityconstants.h"  specbegin(qbelectricitybasevcspec)      describe(@"qbelectricitybasevc", ^{         __block qbelectricitybasevc *electricitybasevc;         __block nsnotificationcenter *mocknotificationcenter;          beforeeach(^{             electricitybasevc = [qbelectricitybasevc new];             mocknotificationcenter = mock([nsnotificationcenter class]);             electricitybasevc.notificationcenter = mocknotificationcenter;         });          aftereach(^{             electricitybasevc = nil;             mocknotificationcenter = nil;         });          it(@"should have notification observer updated electricity usage", ^{             [electricitybasevc addnotificationobservers];             [verify(mocknotificationcenter) addobserver:electricitybasevc selector:@selector(updateelectricityusage)                                                name:kupdatedelectricityusagekey object:nil];         });     });  specend   that test passes correct/best way test this?
you've felt 1 big con of ios viewcontrollers: they suck @ testability.
- viewcontrollers mix logic of managing view , model 
- this leads massive viewcontrollers
 - this violates single responsibility rule 
- this makes code not reusable
 
 
 
another big problem mvc discourages developers writing unit tests. since view controllers mix view manipulation logic business logic, separating out components sake of unit testing becomes herculean task. task many ignore in favour of… not testing anything.
maybe should think using mvvm instead. great article explaining difference of ios mvc , mvvm.
the great thing using mvvm can use databinding using reactive cocoa. here's tutorial explain data binding mvvm , reactive programming in ios.
Comments
Post a Comment