Last Updated: February 25, 2016
·
2.158K
· voidet

Testing Singletons in iOS with Kiwi

A recent problem I ran into whilst getting up to speed with BDD and Kiwi on iOS was testing singletons. By nature singletons are static objects, they shouldn't as they are "instantiated" instead they return an already live copy of themselves for mutation. This was an issue when running multiple tests where you want the singleton to be "fresh" or new between each test.

#import "VVSomethingGood.h"

@implementation VVSomethingGood

static VVSomethingGood *_sharedInstance = nil;
static dispatch_once_t onceToken;

+ (instancetype)sharedInstance {
    dispatch_once(&onceToken, ^{
        if (_sharedInstance == nil) {
            _sharedInstance = [[VVSomethingGood alloc] init];
        }
    });
    return _sharedInstance;
}

Then the magic method to reset the singleton back to a state where the sharedInstance would be recreated via the sharedInstance class method:

//A hook to override singleton, useful for testing
+(void)setSharedInstance:(VVSomethingGood *)instance {
    onceToken = 0; // resets the once_token so dispatch_once will run again
    _sharedInstance = instance;
}

So then in my Kiwi tests I have

[VVSomethingGood setSharedInstance:nil];

Wherever I want my tests to be reset