An elegant library for stubbing HTTP requests with ease in Swift

Related tags

Testing Mockingjay
Overview

Mockingjay

An elegant library for stubbing HTTP requests in Swift, allowing you to stub any HTTP/HTTPS using NSURLConnection or NSURLSession. That includes any request made from libraries such as Alamofire and AFNetworking.

Installation

CocoaPods is the recommended installation method.

pod 'Mockingjay'

Usage

Mockingjay has full integration to XCTest and you simply just need to register a stub, it will automatically be unloaded at the end of your test case. It will also work with the Quick behaviour-driven development framework.

Simple stub using a URI Template, returning a response with the given JSON encoded structure

let body = [ "user": "Kyle" ]
stub(uri("/{user}/{repository}"), json(body))

The uri function takes a URL or path which can have a URI Template. Such as the following:

  • https://github.com/kylef/WebLinking.swift
  • https://github.com/kylef/{repository}
  • /kylef/{repository}
  • /kylef/URITemplate.swift

Stubbing a specific HTTP method with a JSON structure

let body = [ "description": "Kyle" ]
stub(http(.put, uri: "/kylef/Mockingjay"), json(body))

Stubbing everything request to result in an error

let error = NSError()
stub(everything, failure(error))

Stub with a specific HTTP response

stub(everything, http(status: 404))

Note, the http builder can take a set of headers and a body too.

Stub

The stub method in Mockingjay takes two functions or closures, one to match the request and another to build the response. This allows you to easily extend the syntax to provide your own specific functions.

stub(matcher, builder)

Matchers

A matcher is simply a function that takes a request and returns a boolean value for if the stub matches the request.

func matcher(request:URLRequest) -> Bool {
  return true  // Let's match this request
}

stub(matcher, failure(error))

Builders

Builders are very similar to a matcher, it takes a request, and it returns either a success or failure response.

func builder(request: URLRequest) -> Response {
  let response = HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: nil, headerFields: nil)!
  return .success(response, .noContent)
}

stub(matcher, builder)

Generics

You can make use of the builtin generic matchers and builders. These can be used alone, or in conjunction with custom components.

Builtin Matchers

  • everything - Matches every given request.
  • uri(template) - Matches using a URI Template.
  • http(method, template) - Matches using a HTTP Method and URI Template.

Builtin Builders

  • failure(error) - Builds a response using the given error.
  • http(status, headers, data) - Constructs a HTTP response using the given status, headers and data.
  • json(body, status, headers) - Constructs a JSON HTTP response after serialising the given body as JSON data.
  • jsonData(data, status, headers) - Constructs a JSON HTTP response with raw JSON data.

Using JSON files as test fixtures

During setUp, load the JSON file as NSData and use jsonData.

override func setUp() {
  super.setUp()
  let url = Bundle(for: type(of: self)).url(forResource: "fixture", withExtension: "json")!
  let data = try! Data(contentsOf: url)
  stub(matcher, jsonData(data))
}

License

Mockingjay is licensed under the BSD license. See LICENSE for more info.

Comments
  • request.HTTPBody is always nil in custom matcher

    request.HTTPBody is always nil in custom matcher

    I'm setting the HTTPBody property of an NSMutableURLRequest and trying to do some comparison on it inside of a custom matcher.

    However, the property's value is always nil by the time the request reaches the matcher despite it being set prior to that.

    opened by paulyoung 16
  • Problem using MockingJay

    Problem using MockingJay

    I have a model class that fetches data from my server using AlamoOnFire, ObjectMapper and Realm for persistance. Realm introduces the List construct.

    My problem is that MockingJay doesn't seem to be used. The JSON-File from the file-system can be loaded in my test and contains the data that is computed correctly if fetched from server.

    Any idea what could be wrong?

    import XCTest
    import Mockingjay
    import RealmSwift
    @testable import MyApp
    
    class OverviewModelTests: XCTestCase {
    
        override func setUp() {
            super.setUp()
            let path = NSBundle(forClass: self.dynamicType).pathForResource("Overview", ofType: "json")!
            let data = NSData(contentsOfFile: path)!
            stub(everything, builder: jsonData(data))
        }
        //http(.GET, uri: URLs.sharedInstance.overviewItemsUrl())
    
    
        func testFetchOverviewItems() {
    
            let overviewModel = OverviewModel()
    
            overviewModel.fetchOverviewItemList({ (itemList: List<OverviewItem>) -> () in
    
                XCTAssertTrue(itemList.count == 6)
                })
                { (error: ErrorType?) -> () in
                    XCTFail("Error in testFetchOverviewItems ")
                }
        }
    
    
    }
    
    opened by ogezue 14
  • NSURLSessionConfiguration swizzling with Alamofire

    NSURLSessionConfiguration swizzling with Alamofire

    This is a strange one. Mockingjay's initialize() on XCTest is working as expected but the one on NSURLSessionConfiguration never actually fires.

    The swizzle hooks properly if you manually call NSURLSessionConfiguration.initialize(), otherwise MockingjayProtocol never gets pushed into protocolClasses in the configuration.

    Xcode 7.0 (7A220) Alamofire 2.0.0

    Here's the relevant code on Alamofire.

    opened by nwest 12
  • Minimum deployment target 9.1 error Xcode 7.1

    Minimum deployment target 9.1 error Xcode 7.1

    I've just upgraded my Xcode to 7.1 and I'm no longer being able to build Mockingjay due to the following error: Module file's minimum deployment target is ios9.1 v9.1: Do you have any idea how to fix this? Thanks.

    opened by diogoguimaraes 11
  • Using Mockingjay in app target (no XCTest)

    Using Mockingjay in app target (no XCTest)

    I want to use Mockingjay in my app to stub real APIs while they are still in development, so I tried what @kylef suggested in #28, but it is not working because you also need to swizzle the NSURLSessionConfiguration (as the implementation in Mockingjay/XCTest does).

    The final replacement stub method should be:

    func stub(matcher:Matcher, builder:Builder) -> Stub {
        NSURLSessionConfiguration.mockingjaySwizzleDefaultSessionConfiguration()    
        return MockingjayProtocol.addStub(matcher, builder: builder)
    }
    

    Since using Mockingjay without XCTest could be a useful scenario, maybe it is worth having a note in the readme, or even better supporting this natively.

    Another issue is that using the full Mockingjay pod in a test target while using Mockingjay/Core pod in the app creates conflicts on compilation, since if you include both pods they will be compiled as a single framework, I guess (maybe Cocoapods error?). In my opinion, the stub method should be moved to another global place (like Mockingjay.stub), so that it would be available regardless of XCTest, while the XCTest stuff should be moved to a separate framework or even removed entirely, since it is so simple (and much more clear) to just add a removeAllStubs on tearDown method in a test case, like OHHTTPStubs does.

    question 
    opened by alessandroorru 9
  • Matchers running slowly

    Matchers running slowly

    I've got a test that's a sort of integration/stress test for my networking code. When I switched from having my networking code check for cached files my tests placed in a temp directory to using Mockingjay, the tests slowed down a lot. I profiled with Instruments, and found that most of the test's time is being spent in MockingjayProtocol.stubForRequest(NSURLRequest) -> Stub?, and specifically in my custom matcher, which looks like this:

    public func urlPathEquals(path: String) -> (request:NSURLRequest) -> Bool {
        return { request in
            request.URL?.path == path
        }
    }
    

    Before this test case runs, I loop through my large number of JSON files and create a matcher like this for each one, so there is a large number of mocks configured. What can I do to speed this up? My test is taking so long that it's causing a failure on my build server.

    question 
    opened by abbeycode 7
  • Carthage - Mockingjay for iOS

    Carthage - Mockingjay for iOS

    I use Carthage and it uses shared schemes to build dependencies but there is only a target for Mac OS X, could iOS be added so it works with Carthage?

    question 
    opened by TomasLinhart 7
  • Isn't better use URITemplate 2.0.0 in last tag?

    Isn't better use URITemplate 2.0.0 in last tag?

    In 1.3.0 release and master branch you're using URI Template 2.0.0, but when I use the last tag (1.3.1) the URITemplate dependency used is 1.4.0. Isn't better use also version 2.0.0 in last tag?

    question 
    opened by RafaelPlantard 6
  • Preventing unintended network requests for unmatched requests

    Preventing unintended network requests for unmatched requests

    In my current use of Mockingjay I find that if my implementation is somehow incorrect and the matcher returns false, actual network requests are made.

    This is all working as expected, but I would prefer it if no networks requests were made, and any unintended requests cause a test to fail.

    Is this somehow possible already? If not, I think something like an everythingExcept matcher could be useful.

    opened by paulyoung 6
  • Xcode can't find stub or matcher now

    Xcode can't find stub or matcher now

    We have jsonData now but now Xcode is complaining that stub and matcher are unavailable. Not sure why.

    import Foundation
    import Mockingjay
    
    class TestModel: NSObject {
    
        class func testRequest() {
            let path = NSBundle.mainBundle().pathForResource("Plaid", ofType: "json")
            let data = NSData(contentsOfFile: path!)!
    
            stub(matcher, builder: jsonData(data))
        }
    
    }
    

    Ideas?

    screen shot 2015-10-12 at 10 51 24 am question 
    opened by noisypigeon 6
  • Does it work with a Xcode 7 UI test target?

    Does it work with a Xcode 7 UI test target?

    I'm trying to make Mockingjay working within a UI Test target but I cannot make it run properly. It seems that stubs are never used when the code runs from a UI Test target.

    question 
    opened by ariok 6
  • Swift Package Manager Support

    Swift Package Manager Support

    Hi.

    This pull-request merges the current bug fixes and support for Swift Package Manager into a working code base.

    You may consider merging the changes in a different order, but for now this works as reference for others looking for a working package with SPM support.

    Hope this helps :) 👍

    opened by billbonney 0
  • Build with Swift 5 fails if '3.0.0-alpha.1' version is not explicitly specified in the Podfile.

    Build with Swift 5 fails if '3.0.0-alpha.1' version is not explicitly specified in the Podfile.

    By default cocoapods uses the 2.0.1 version of Mockingjay which makes the build fail when using Swift 5 due to issue #110.

    You have to specify pod 'Mockingjay', '3.0.0-alpha.1' in the Podfile to get the latest version.

    Maybe this is obvious for people who are used to cocoapods, but it took me a while to figure it out. Putting that in the installation instructions in the README might save others some time.

    opened by henleo 0
  • Could not build Objective-C module 'Mockingjay'

    Could not build Objective-C module 'Mockingjay'

    I tried to use cocopod to import lib inside of my project but still run into problem like this Could not build Objective-C module 'Mockingjay' I used Swift 5 Screen Shot 2020-03-05 at 3 41 47 PM

    opened by codedeman 0
  • Custom matcher runs twice if matcher returns true

    Custom matcher runs twice if matcher returns true

    I am running stub request test in XCTest and my case is as following:

    func testExample() {
            func matchPath(request: URLRequest) -> Bool {
                let path = request.url?.path
                return path != nil // setup a breakpoint on this line and you can see it runs twice
            }
    
            var responseBodyJson: [String: String] = [:]
            responseBodyJson["appId"] = "1"
            stub(matchPath, json(responseBodyJson, status: 200, headers: nil))
            
            let urlPath: String = "http://www.stackoverflow.com"
            let url: URL = URL(string: urlPath)!
            let request1: URLRequest = URLRequest(url: url)
            let response: AutoreleasingUnsafeMutablePointer<URLResponse?>? = nil
            do{
                let dataVal = try NSURLConnection.sendSynchronousRequest(request1, returning: response)
                print(response)
                do {
                    if let jsonResult = try JSONSerialization.jsonObject(with: dataVal, options: []) as? NSDictionary {
                        print("Synchronous\(jsonResult)")
                    }
                } catch let error as NSError {
                    print(error.localizedDescription)
                }
            }catch let error as NSError
            {
                print(error.localizedDescription)
            }
    }
    
    opened by trinhhunganh 0
  • Could not find auto-linked framework

    Could not find auto-linked framework

    I have successfully installed via Cocoapods, imported the module in my XCTest class, and added methods. When I try and run my tests I see the below error. I have tried to import the project manually with no luck, have the framework in my linked frameworks for the test target. Any ideas?

    image

    Thanks

    opened by christinasund 5
Releases(3.0.0-alpha.1)
  • 3.0.0-alpha.1(Jun 7, 2019)

  • 2.0.1(Nov 18, 2017)

  • 2.0.0(Nov 14, 2016)

    This release adds support for Swift 3.0.

    Breaking

    • Responses now use a Download enum instead of an optional NSData. This means you must use the following API:

      .success(response, .noContent)
      .success(response, .content(data))
      

      Previously:

      .Success(response, nil)
      .Success(response, data)
      

    Enhancements

    • Adds support for streaming stubbed response data.

      .success(response, .streamContent(data, inChunksOf: 1024))
      
    Source code(tar.gz)
    Source code(zip)
  • 1.3.1(Oct 7, 2016)

  • 1.3.0(Sep 28, 2016)

  • 1.2.1(May 10, 2016)

  • 1.2.0(May 10, 2016)

    Enhancements

    • Swift 2.2 support has been added.

    Bug Fixes

    • Mockingjay will now add it's own protocol to NSURLSessionConfiguration default and ephemeral session configuration on load. This fixes problems when you create a session and then register a stub before we've added the Mockingjay protocol to NSURLSessionConfiguration.
      #50
    Source code(tar.gz)
    Source code(zip)
Owner
Kyle Fuller
Kyle Fuller
A collection of useful test helpers designed to ease the burden of writing tests for iOS applications.

MetovaTestKit is a collection of useful test helpers designed to ease the burden of writing tests for iOS applications. Requirements Installation Usag

null 23 Aug 29, 2021
Stub your network requests easily! Test your apps with fake network data and custom response time, response code and headers!

OHHTTPStubs OHHTTPStubs is a library designed to stub your network requests very easily. It can help you: test your apps with fake network data (stubb

Olivier Halligon 4.9k Dec 29, 2022
Mock Alamofire and URLSession requests without touching your code implementation

Mocker is a library written in Swift which makes it possible to mock data requests using a custom URLProtocol. Features Requirements Usage Activating

WeTransfer 898 Dec 26, 2022
Automatic testing of your Pull Requests on GitHub and BitBucket using Xcode Server. Keep your team productive and safe. Get up and running in minutes. @buildasaur

Buildasaur Automatic testing of your Pull Requests on GitHub and BitBucket using Xcode Server. Keep your team productive and safe. Get up and running

Buildasaurs 774 Dec 11, 2022
Mockingbird was designed to simplify software testing, by easily mocking any system using HTTP/HTTPS

Mockingbird Mockingbird was designed to simplify software testing, by easily mocking any system using HTTP/HTTPS, allowing a team to test and develop

FARFETCH 183 Dec 24, 2022
This is a Swift port of Ruby's Faker library that generates fake data.

This is a Swift port of Ruby's Faker library that generates fake data. Are you still bothered with meaningless randomly character strings? Just relax

Vadym Markov 1.6k Jan 3, 2023
PinpointKit is an open-source iOS library in Swift that lets your testers and users send feedback with annotated screenshots using a simple gesture.

PinpointKit is an open-source iOS library in Swift that lets your testers and users send feedback with annotated screenshots using a simple gesture. F

Lickability 1.1k Jan 6, 2023
The XCTest Project, A Swift core library for providing unit test support

XCTest The XCTest library is designed to provide a common framework for writing unit tests in Swift, for Swift packages and applications. This version

Apple 1k Jan 4, 2023
MockSwift is a Mock library written in Swift.

Welcome to MockSwift MockSwift allows you to write mocks and make better tests. Because MockSwift is an open source library 100% written in Swift, it

Jordhan Leoture 82 Dec 17, 2022
Test Library for Swift's Error Handling

CatchingFire CatchingFire is a Swift test framework, which helps making expectations against the error handling of your code. It provides for this pur

Marius Rackwitz 75 May 16, 2022
Lightweight touch visualization library in Swift. A single line of code and visualize your touches!

TouchVisualizer is a lightweight pure Swift implementation for visualising touches on the screen. Features Works with just a single line of code! Supp

Morita Naoki 851 Dec 17, 2022
A Swift test double library. Guava - looks like an apple but it's not.

Guava Guava helps you to make your unit tests more flexible. It allows you to replace parts of your system under test with a test double objects. Tabl

Denis Chagin 10 Mar 22, 2022
Freezer is a library that allows your Swift tests to travel through time by mocking NSDate class.

Freezer Freezer is a library that allows your Swift tests to travel through time by mocking NSDate class. Usage Once Freezer.start() has been invoked,

Sergey Petrov 8 Sep 24, 2022
Trust - Swift DCI Test Library

Trust Swift - DCI Pattern Test Library Support SPM How to use ? struct User {

gitaek lee 1 Feb 13, 2022
SwiftCheck is a testing library that automatically generates random data for testing of program properties

SwiftCheck QuickCheck for Swift. For those already familiar with the Haskell library, check out the source. For everybody else, see the Tutorial Playg

TypeLift 1.4k Dec 21, 2022
ShortWebCore - This iOS library lets you run automations on Web Views.

This iOS library lets you run automations on Web Views. Example (Optional) Declare class conforming to AutomationRunnerDelegate: import S

Emma Cold 19 Dec 26, 2022
Library for unifying the approach to network mocking in iOS unit- & UI-tests.

TinkoffMockStrapping Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements Installati

Online financial ecosystem 22 Jan 3, 2023
A simple and lightweight matching library for XCTest framework.

Match A simple and lightweight matching library for XCTest framework. Getting started Swift Package Manager You can add Match to your project by addin

Michał Tynior 6 Oct 23, 2022
A Mac and iOS Playgrounds Unit Testing library based on Nimble.

Spry Spry is a Swift Playgrounds Unit Testing library based on Nimble. The best thing about Spry is that the API matches Nimble perfectly. Which means

Quick 327 Jul 24, 2022