{"id":3467,"date":"2014-02-20T15:58:14","date_gmt":"2014-02-20T15:58:14","guid":{"rendered":"http:\/\/ushipblogsubd.wpengine.com\/?p=3467"},"modified":"2025-09-03T16:07:35","modified_gmt":"2025-09-03T16:07:35","slug":"unit-testing-around-singletons-with-ocmock","status":"publish","type":"post","link":"https:\/\/ushipblogsubd.wpengine.com\/shipping-code\/unit-testing-around-singletons-with-ocmock\/","title":{"rendered":"Unit Testing Around Singletons with OCMock"},"content":{"rendered":"<p dir=\"ltr\"><span style=\"line-height: 1.5em\">Whether you agree with the use of <\/span><a style=\"line-height: 1.5em\" href=\"http:\/\/en.wikipedia.org\/wiki\/Singleton_pattern#cite_note-1\" target=\"_blank\" rel=\"noopener\">singletons<\/a><span style=\"line-height: 1.5em\"> or not, you can\u2019t completely avoid them as an iOS developer. Apple provides some critical functionality through singletons exposed in its iOS SDK, but it can be quite difficult to write unit tests around code that accesses them. In this article, I will describe a couple of techniques for managing this. First though, let\u2019s set up an example of the sort of problem I\u2019m talking about.<\/span><\/p>\n<h1>Problem<\/h1>\n<p dir=\"ltr\">Let\u2019s say we have an app which is set up to register itself for push notifications. We\u2019ve already written a simple proof-of-concept view controller with a switch for the user to enable or disable these notifications. The code is written and working well, but looks terrible.<\/p>\n<p dir=\"ltr\" style=\"text-align: center\">\u00a0<img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/lrjjwXamKOt8NbkUR5fmYZBb91WFqFWaBYRKANecXFcdA62utlGYzzqUe5-D1YVDkJS2VhOVHZdvfbbug1XLPFcDd3v_R1u1sKM_YBPJoPKkXFvs7fwj9p6KkA\" alt=\"\" width=\"434px;\" height=\"704px;\" \/><\/p>\n<p dir=\"ltr\">I mean how is the user supposed to know what that switch does? \u00a0And is it bugging anyone else that the switch isn\u2019t even centered? Clearly, we should make this screen a bit more interesting and add some new features. Maybe a label\u2026 some more colors\u2026oh! how about some animation?<\/p>\n<p dir=\"ltr\"><span style=\"line-height: 1.5em\">Whatever we decide to do, we want to make sure we don\u2019t break the existing functionality. \u00a0The switch works, but there are no unit tests to verify that it does.<\/span><\/p>\n<p><strong><span style=\"font-size: 2em;line-height: 1.5em\">Solution<\/span><\/strong><\/p>\n<p dir=\"ltr\">While our designer figures out what features we want to add, let&#8217;s give this code some test coverage. \u00a0Let\u2019s start by taking a look at the code we\u2019re going to work with. \u00a0Here is the interface for the view controller.<\/p>\n<p>[cc lang=&#8221;objc&#8221;]<br \/>\n@interface SettingsViewController : UIViewController<br \/>\n{<br \/>\n@property (nonatomic, strong) IBOutlet UISwitch *pushNotificationsSwitch;<br \/>\n&#8211; (IBAction)pushNotificationsSwitchWasToggled:(id)sender;<br \/>\n}<br \/>\n[\/cc]<\/p>\n<p dir=\"ltr\"><span style=\"line-height: 1.5em\">&#8230;and here\u2019s the implementation.<\/span><\/p>\n<p>[cc lang=&#8221;objc&#8221;]<br \/>\n@implementation SettingsViewController<\/p>\n<p>&#8211; (void)viewDidLoad<br \/>\n{<br \/>\n\/\/create the switch<br \/>\nself.pushNotificationsSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 50, 30)];<\/p>\n<p>\/\/link it to the action method<br \/>\n[self.pushNotificationsSwitch addTarget:self action:@selector(pushNotificationsSwitchWasToggled:) forControlEvents:UIControlEventValueChanged];<br \/>\n}<\/p>\n<p>&#8211; (IBAction)pushNotificationsSwitchWasToggled:(id)sender<br \/>\n{<br \/>\nUISwitch *toggleSwitch = sender;<br \/>\nif (toggleSwitch.on)<br \/>\n{<br \/>\n\/\/if the switch was toggled on, register for push notifications<br \/>\n[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert)];<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\n\/\/if it was toggled off, unregister<br \/>\n[[UIApplication sharedApplication] unregisterForRemoteNotifications];<br \/>\n}<br \/>\n}<br \/>\n@end<br \/>\n[\/cc]<\/p>\n<p dir=\"ltr\">We\u2019ll first try to write a test to verify that the app gets registered for push notifications when that lonely switch gets flipped to ON.<\/p>\n<p>[cc lang=&#8221;objc&#8221;]<br \/>\n&#8211; (void)testToggleOnRegistersForPushNotifications_On<br \/>\n{<br \/>\n\/\/given the view controller is loaded<br \/>\nSettingsViewController *sut = [[SettingsViewController alloc] init];<br \/>\n[sut view];<\/p>\n<p>\/\/given the switch is toggled on<br \/>\n[sut.pushNotificationsSwitch setOn:YES];<\/p>\n<p>\/\/when the view controller is notified that the switch was toggled<br \/>\n[sut pushNotificationsSwitchWasToggled:sut.pushNotificationsSwitch];<\/p>\n<p>\/\/then the app should register for notifications with alerts and badges<br \/>\n\/\/?? how do we verify this<br \/>\n}<br \/>\n[\/cc]<\/p>\n<p dir=\"ltr\">Let\u2019s walk through what\u2019s going on here. \u00a0We create an instance of the <a href=\"http:\/\/en.wikipedia.org\/wiki\/System_under_test\" target=\"_blank\" rel=\"noopener\">SUT<\/a>, then simulate the act of flipping the switch to ON. Unfortunately, we\u2019re not sure now how to verify that the switch did what it\u2019s supposed to because all it does is call methods on the <strong>UIApplication<\/strong> singleton! To finish the test, we need to figure out a way to expose <strong>[UIApplication sharedApplication]<\/strong> as a dependency. One way to do that is through <a href=\"http:\/\/en.wikipedia.org\/wiki\/Dependency_injection\" target=\"_blank\" rel=\"noopener\">dependency injection<\/a>.<\/p>\n<h1>With Dependency Injection<\/h1>\n<p dir=\"ltr\">To use dependency injection, we\u2019ll have to modify our view controller class so we can provide an instance of <strong>UIApplication<\/strong> that it can work with. Then the app can use the real <strong>sharedApplication<\/strong> instance, while the test uses a mock object. \u00a0To accomplish this, we\u2019ll add a new property to the <strong>SettingsViewController<\/strong> interface&#8230;<\/p>\n<p>[cc lang=&#8221;objc&#8221;]<br \/>\n@property (nonatomic, strong) UIApplication *application;<br \/>\n[\/cc]<\/p>\n<p dir=\"ltr\"><span style=\"line-height: 1.5em\">&#8230;and modify our view controller implementation to use it.<\/span><\/p>\n<p>[cc lang=&#8221;objc&#8221;]<br \/>\n&#8211; (UIApplication*)application<br \/>\n{<br \/>\nif (!_application)<br \/>\n{<br \/>\n_application = [UIApplication sharedApplication];<br \/>\n}<br \/>\nreturn _application;<br \/>\n}<\/p>\n<p>&#8211; (IBAction)pushNotificationsSwitchWasToggled:(id)sender<br \/>\n{<br \/>\nUISwitch *toggleSwitch = sender;<br \/>\nif (toggleSwitch.on)<br \/>\n{<br \/>\n[self.application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert)];<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\n[self.application unregisterForRemoteNotifications];<br \/>\n[\/cc]<\/p>\n<p dir=\"ltr\">The first method here is lazy-loading the application property so that it defaults to <strong>[UIApplication sharedApplication]<\/strong> when the app is running for real. \u00a0Then we changed <strong>pushNotificationsSwitchWasToggled:<\/strong> to refer to <strong>self.application<\/strong> instead of <strong>[UIApplication sharedApplication]<\/strong>.<\/p>\n<p dir=\"ltr\">With that out of the way, we can finish our test by initializing the view controller with a mock object before the switch is toggled. The test can then monitor that mock to verify the behavior we\u2019re expecting. Here\u2019s our unit test again. This time, the test is using the mocking framework\u00a0<a href=\"http:\/\/ocmock.org\/\" target=\"_blank\" rel=\"noopener\">OCMock<\/a> to create the mock, set up expectations, and verify them.<\/p>\n<p>[cc lang=&#8221;objc&#8221;]<br \/>\n&#8211; (void)testToggleOnRegistersForPushNotifications_On<br \/>\n{<br \/>\n\/\/given<br \/>\nid mockApplication = [OCMockObject niceMockForClass:[UIApplication class]];<br \/>\n[[mockApplication expect] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert)];<\/p>\n<p>SettingsViewController *sut = [[SettingsViewController alloc] init];<br \/>\nsut.application = mockApplication;<br \/>\n[sut view];<br \/>\n[sut.pushNotificationsSwitch setOn:YES];<\/p>\n<p>\/\/when<br \/>\n[sut pushNotificationsSwitchWasToggled:sut.pushNotificationsSwitch];<\/p>\n<p>\/\/then<br \/>\n[mockApplication verify];<br \/>\n}<br \/>\n[\/cc]<\/p>\n<p dir=\"ltr\">Here our mock instance is configured to expect a message with the signature <strong>registerForRemoteNotificationTypes:<\/strong> and some very specific arguments. We then simulate flipping the switch to ON. At the end of the test, we ask the mock to verify that the expected method was actually called. If not, the test raises an exception on that last line and the test is reported as a failure.<\/p>\n<p dir=\"ltr\">You\u2019ll notice that to use dependency injection, we had to modify a lot of our app\u2019s code to make it testable. \u00a0Imagine <strong>SettingsViewController<\/strong> was a much larger and more complicated class without any unit test coverage. It could be quite intimidating to have to change that code just to make it testable. You could break it just trying to test it. If for some reason you can\u2019t or don\u2019t want to take that risk, there\u2019s another way to test this code.<\/p>\n<h1>Without Dependency Injection<\/h1>\n<p dir=\"ltr\">In the case of our <strong>SettingsViewController<\/strong>, we can actually stub out this singleton dependency without resorting to dependency injection. <a href=\"http:\/\/ocmock.org\/\" target=\"_blank\" rel=\"noopener\">OCMock<\/a> in particular is actually quite helpful in this case. With the help of OCMock, we can temporarily replace the singleton instance with a mock object that can be monitored by our test.<\/p>\n<p dir=\"ltr\">Here\u2019s that same test again, but this time, we\u2019ll do our mocking <em>without<\/em> dependency injection.<\/p>\n<p>[cc lang=&#8221;objc&#8221;]<br \/>\n&#8211; (void)testToggleOnRegistersForPushNotifications_On<br \/>\n{<br \/>\n\/\/given a mock UIApplication<br \/>\nid mockApplication = [OCMockObject niceMockForClass:[UIApplication class]];<br \/>\n[[[mockApplication stub] andReturn:mockApplication] sharedApplication];<br \/>\n[[mockApplication expect] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert)];<\/p>\n<p>\/\/given the view controller is loaded<br \/>\nSettingsViewController *sut = [[SettingsViewController alloc] init];<br \/>\n[sut view];<\/p>\n<p>\/\/given the switch is toggled on<br \/>\n[sut.pushNotificationsSwitch setOn:YES];<\/p>\n<p>\/\/when the view controller is notified that the switch was toggled<br \/>\n[sut pushNotificationsSwitchWasToggled:sut.pushNotificationsSwitch];<\/p>\n<p>\/\/then the app should register for notifications with alerts and badges<br \/>\n[mockApplication verify];<\/p>\n<p>\/\/finally clean up the mock (VERY IMPORTANT)<br \/>\n[mockApplication stopMocking];<br \/>\n}<br \/>\n[\/cc]<\/p>\n<p dir=\"ltr\">Here we simply stub out the singleton accessor method and force it to return our mock object. Now, whenever any code in the app calls <strong>[UIApplication sharedApplication]<\/strong>, it will actually get this instance of <strong>OCMockObject<\/strong> instead.<\/p>\n<p dir=\"ltr\">You may have noticed that the first time we wrote this test we didn\u2019t call <strong>stopMocking<\/strong> at the end. Normally, at the end of a test, you don\u2019t have to worry about cleaning up a mock instance like this. A normal mock just evaporates as soon as it falls out of scope. But not this one. Since we\u2019re mocking a singleton, the instance won\u2019t actually fall out of scope after the test.<\/p>\n<p dir=\"ltr\">Try this to see what I mean. Comment out the <strong>stopMocking<\/strong> line in the test above and add this test at the end of the same test suite:<\/p>\n<p>[cc lang=&#8221;objc&#8221;]<br \/>\n&#8211; (void)testZ_MockWasActuallyDestroyed<br \/>\n{<br \/>\nid app = [UIApplication sharedApplication];<br \/>\nXCTAssert([app isMemberOfClass:[UIApplication class]],<br \/>\n@&#8221;a mock for UIApplication sharedApplication was not cleaned up!&#8221;);<br \/>\n}<br \/>\n[\/cc]<\/p>\n<p dir=\"ltr\">The \u2018Z\u2019 at the front of the test name just forces it to run last. This is because OCUnit\/XCUnit tests run in alphabetical order. \u00a0With the call to <strong>stopMocking<\/strong> commented out, you\u2019ll see that this new test fails.<\/p>\n<p dir=\"ltr\">So it\u2019s VERY IMPORTANT that you call OCMock\u2019s <strong>stopMocking<\/strong> method on the mock singleton object when you\u2019re done with it. Forgetting this step means your mock singleton instance will survive and potentially influence the outcome of other unit tests.<\/p>\n<p dir=\"ltr\">You can find a <a href=\"https:\/\/github.com\/uShip\/ocmock-singletons-example\" target=\"_blank\" rel=\"noopener\">sample project on github<\/a> which shows all the code above in action. \u00a0It also includes some alternate unit tests which demonstrate doing some of the same things using Jon Reid&#8217;s <a href=\"https:\/\/github.com\/jonreid\/OCMockito\" target=\"_blank\" rel=\"noopener\">OCMockito<\/a>, instead of OCMock.<\/p>\n<p>[amp-cta id=&#8217;8486&#8242;]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Whether you agree with the use of singletons or not, you can\u2019t completely avoid them as an iOS developer. Apple provides some critical functionality through singletons exposed in its iOS SDK, but it can be quite difficult to write unit tests around code that accesses them. In this article, I will describe a couple of&#8230;<a class=\"read-more\" href=\"https:\/\/ushipblogsubd.wpengine.com\/shipping-code\/unit-testing-around-singletons-with-ocmock\/\"> Read More<\/a><\/p>\n","protected":false},"author":5,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[295,2],"tags":[15,16,17,297,19],"class_list":["post-3467","post","type-post","status-publish","format-standard","hentry","category-shipping-code","category-company-news","tag-ios-developer","tag-native-mobile-app","tag-ocmock","tag-shipping-code","tag-unit-testing"],"acf":{"blog_post_content":[{"acf_fc_layout":"blog_post_entry_footer","blog_post_entry_footer_cta":[{"blog_post_entry_footer_cta_url":"https:\/\/www.uship.com\/","blog_post_entry_footer_cta_text":"Ready to Ship Something?","blog_post_entry_footer_onclick":""}]}]},"_links":{"self":[{"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/posts\/3467","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/comments?post=3467"}],"version-history":[{"count":0,"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/posts\/3467\/revisions"}],"wp:attachment":[{"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/media?parent=3467"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/categories?post=3467"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/tags?post=3467"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}