{
  "$type": "site.standard.document",
  "coverImage": {
    "$type": "blob",
    "ref": {
      "$link": "bafkreibseyksgtir2t6o6dezvvvykkgr5wnmjrf6r6ugd6wyaaw42aaxqi"
    },
    "mimeType": "image/png",
    "size": 75941
  },
  "description": "<p>How to use protocols to mock types in Swift to test your iOS apps without relying on Objective-C runtime hacks and swizzles.</p>",
  "path": "/mocks-in-swift-via-protocols",
  "publishedAt": "2015-10-01T00:00:00.000Z",
  "site": "at://did:plc:wm37qzgdjvwztq6loytrtpul/site.standard.publication/3mgjrev2z22sw",
  "textContent": "Testing the nitty gritty dirty innards of a lot of iOS apps has been difficult\nin the past. A variety of tools and methodologies have been developed over time,\nincluding a couple mocking frameworks like OCMock or\nOCMockito. With the advent of Swift,\nthese frameworks have seen their implementations rendered useless, since they\ndepend heavily on the Objective-C runtime.But with Swift, there might be a better way to setup our programs that don't\nrequire Objective-C funtime runtime hacks and swizzles.Mocking UIApplicationLet's take a look at an example which mocks out our favorite hard-to-test class,\nUIApplication.In our example, let's work on a type that handles push notifications.struct PushNotificationController {\n}The goal of this type will be to have some function which we can call to ask the\nuser for the permission to send push notifications, via UIApplication's\nregisterUserNotificationSettings(_:), maybe handle some pushes and delegate\ncalls for device tokens and such, etc.We want to trigger push registration to be off of some state, say maybe once our\nuser logs in, so that we don't bombard our new users with alerts without\nactually using our app first. A naïve approach might be to just create some\nfunction which calls\nUIApplication.sharedApplication().registerUserNotificationSettings(_:).struct PushNotificationController {\n    var user: User {\n        didSet {\n            let application = UIApplication.sharedApplication()\n            application.registerUserNotificationSettings(_:)\n        }\n    }\n}Easy, right? Okay, now let's go test this functionality so we know that we can\nwrite some unit test around PushNotificationController to know that we\nactually do register for push notifications when we give it a user.import XCTest\n\nclass PushNotificationControllerTests: XCTestCase {\n    func testControllerRegistersForPushesAfterSettingAUser() {\n        let controller = PushNotificationController()\n        controller.user = User()\n        // uhhh... now what?\n    }\n}What's in a Test?Let's take a step back here and figure out what has made our code untestable.\nThere's a couple things that we're fighting against. We don't own\nUIApplication or it's sharedApplication() method, so it's a bit difficult to\nsubstitute our own functionality into these. Additionally, we don't have a way\nto know if calling\nUIApplication.sharedApplication().registerUserNotificationSettings(_:) really\ndoes anything in our unit test. We can't assert that the screen has the alert\nview on it now.What are we really trying to test here? We shouldn't be testing UIKit, there's\na few Apple engineers out there whose job it is to do that. We really just want\nto test that our type asks the relevant party to register for push\nnotifications, and in this case it just so happens that the relevant party is\na UIApplication.Protocol-Oriented ProgrammingSo how can we get a bit of flexibility here? How can we verify our type?I propose that protocols are the best way to mock types in Swift.Let's create a protocol here to stand in for UIApplication.protocol PushNotificationRegistrar {\n    func registerUserNotificationSettings(_:)\n}Super simple. A PushNotificationRegistrar is any type that has a function\nregisterUserNotificationSettings(_:) to call.Next, let's dependency inject a PushNotificationRegistrar into our\nPushNotificationController.struct PushNotificationController {\n    let registrar: PushNotificationRegistrar\n    init(registrar: PushNotificationRegistrar) {\n        self.registrar = registrar\n    }\n}Perfect. Now instead of calling registerUserNotificationSettings(_:) on\nUIApplication.sharedApplication(), let's instead call it on our registrar.struct PushNotificationController {\n    let registrar: PushNotificationRegistrar\n    init(registrar: PushNotificationRegistrar) {\n        self.registrar = registrar\n    }\n\n    var user: User {\n        didSet {\n            registrar.registerUserNotificationSettings(_:)\n        }\n    }\n}Beautiful! Now there's no more UIApplication.sharedApplication() to be seen!\nLess global state gives us a bit more wiggle room in our unit tests.Hooking up UIApplication with PushNotificationRegistrarBut if we don't have UIApplication.sharedApplication() ever, how do we get our\napplication to register, you ask? This is where an amazing part of Swift's\nelegance comes into play.We can conform any UIApplication type to PushNotificationRegistrar in one\nline of code:extension UIApplication: PushNotificationRegistrar {}Boom. Done. Since UIApplication already has a method named\nregisterUserNotificationSettings(_:), it's already implementing our protocol.\nIn our application, we can simply just create a PushNotificationController in\nour application delegate, say in\napplication(_:didFinishLaunchingWithOptions:), like so:extension AppDelegate: UIApplicationDelegate {\n    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {\n        let controller = PushNotificationController(application: application)\n        controller.user = User()\n    }\n}and just like that, we're on our way to registering!Testing with Mocks via ProtocolsNow let's write a test around it. In this case, we don't want to give it a\nUIApplication because it's hard for us to get one and it's simply not\ntestable, like we mentioned before. So instead, let's put together a quick type\nthat does some faux registration for us.import XCTest\n\nclass PushNotificationControllerTests: XCTestCase {\n    func testControllerRegistersForPushesAfterSettingAUser() {\n        class FauxRegistrar: PushNotificationRegistrar {\n            var registered = false\n            func registerUserNotificationSettings(notificationSettings: UIUserNotificationSettings) {\n                registered = true\n            }\n        }\n\n        let registrar = FauxRegistrar()\n        var controller = PushNotificationController(registrar: registrar)\n        controller.user = User()\n        XCTAssertTrue(registrar.registered)\n    }\n}Et volia! We just created a test that our application should register for push\nnotifications after setting a user!What Would Crusty Do?Creating mocks via protocols in Swift is great for reasons beyond just unit\ntesting UIApplication methods. Protocols contribute greatly in creating\nboundaries around pieces\nof your architecture and can make sure your make sure your software doesn't\nbecome too crusty.This isn't anything new to Swift, but rather certainly a pattern that is very\ntrivial to implement in many places now. Protocol extensions with default\nimplementations might even push this method forward more as Swift 2 develops\nmore.You can find a playground demoing some functionality of this here:\nhttps://gist.github.com/eliperkins/8f4115151497dc1953ea",
  "title": "Mocks in Swift via Protocols"
}