Latest 1.0.0
Homepage https://github.com/announce/MockURLSession
License MIT
Platforms osx 10.9, ios 8.0, requires ARC
Authors

Build Status
CocoaPods

Are you a dependency injection devotee? Let’s mock NSURLSession together.

Features

  • No need to modify production code to mock NSURLSession
  • Customizable URL matching logic to mock responses
  • Testable that the mocked responses are surely called

Installation

CocoaPods (iOS 8+, OS X 10.9+)

You can use Cocoapods to install MockURLSession by adding it to your Podfile:

platform :ios, '8.0'
use_frameworks!

target 'MyAppTest' do
    pod 'MockURLSession'
end

Note that this requires CocoaPods version 36, and your iOS deployment target to be at least 8.0.

Usage

Quick glance

Let’s take a case to test MyApp below.

class MyApp {
    static let apiUrl = NSURL(string: "https://example.com/foo/bar")!
    let session: NSURLSession
    var data: NSData?
    var error: NSError?
    init(session: NSURLSession = NSURLSession.sharedSession()) {
        self.session = session
    }
    func doSomething() {
        session.dataTaskWithURL(MyApp.apiUrl) { (data, _, error) in
            self.data = data
            self.error = error
        }.resume()
    }
}

In the test code,

import MockURLSession

and write testing by any flamewrorks you prefer sush as XCTest (Written by print here).

// Initialization
let session = MockURLSession()
// Or, use shared instance as `NSURLSession` provides
MockURLSession.sharedSession()

// Setup a mock response
let data = "Foo 123".dataUsingEncoding(NSUTF8StringEncoding)!
session.registerMockResponse(MyApp.apiUrl, data:data)

// Inject the session to the target app code and the response will be mocked like below
let app = MyApp(session: session)
app.doSomething()

print(NSString(data:app.data!, encoding:NSUTF8StringEncoding)!)  // Foo 123
print(app.error)    // nil

// Make sure that the data task is resumed in the app code
print(session.resumedResponse(MyApp.apiUrl) != nil)  // true

URL matching customization

// Customize URL matching logic if you prefer
class Normalizer: MockURLSessionNormalizer {
    func normalizeUrl(url: NSURL) -> NSURL {
        // Fuzzy matching example
        let components = NSURLComponents()
        components.host = url.host
        components.path = url.path
        return components.URL!
    }
}
// Note that you should setup the normalizer before registering mocked response
let data = NSKeyedArchiver.archivedDataWithRootObject(["username": "abc", "age": 20])
let session = MockURLSession()
session.normalizer = Normalizer()
session.registerMockResponse(MyApp.apiUrl, data:data)

Disclosure

Inspirations

Development tips

A long way to bump up spec version

  1. Xcode: MockURLSession > Identity > Version
  2. Pod: s.version in MockURLSession.podspec
  3. Git: git tag 1.0.0 && git push origin --tag
  4. Release by pod trunk push MockURLSession.podspec

Latest podspec

{
    "name": "MockURLSession",
    "version": "1.0.0",
    "summary": "MockURLSession provides a way to mock NSURLSession.",
    "homepage": "https://github.com/announce/MockURLSession",
    "license": {
        "type": "MIT"
    },
    "authors": {
        "Kenta Yamamoto": "http://twitter.com/i05"
    },
    "source": {
        "git": "https://github.com/announce/MockURLSession.git",
        "tag": "1.0.0"
    },
    "source_files": "MockURLSession/*.swift",
    "requires_arc": true,
    "platforms": {
        "osx": "10.9",
        "ios": "8.0"
    }
}

Pin It on Pinterest

Share This