Skip to content
A small but nifty Swift unit test framework for stubbing network calls.
Swift Objective-C Ruby
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
Shawshank.xcodeproj
Shawshank
ShawshankTests
.gitignore
LICENSE
README.md
Shawshank.podspec

README.md

Shawshank

"I guess it comes down to a simple choice, really. Get busy testing or get busy crying." The Shawshank Redemption

As seen in Testing Tips & Tricks from WWDC2018 Using an URLProtocol subclass is a great way to mock responses from network calls in unit tests, but it can be laborious to setup. The goal of Shawshank was to make mocking a network response a one-liner.

It does 2 things: creates a way to match network requests, and specifies what sort of response to return if the match is true.

Installation

Carthage

In your Cartfile use:

github "atetlaw/shawshank"

Shawshank only needs to be added to your unit testing target not your app's main target. Remember to add the Carthage run script phase to your testing target, as well as adding Shawshank.framework to your Link Binaries With Libraries phase (Just click on the + button, the Add Other... button, and select the Shawshank.framework file in the Carthage/Build folder.)

Cocoapods

Add pod 'Shawshank' to your Podfile, but limit it to your testing target like so:

target 'MyAppTests' do
    pod 'Shawshank'
end

Where MyAppTests is the name of your app's unit test target. Then run a pod install.

API Examples

Swift

// Match any requests to `http:www.example.com` and return the HTTP status: Not Permitted
Shawshank.take(matching: .scheme("http") && .host("www.example.com")).httpStatus(.notPermitted)
let json = Bundle(for: ShankPublicAPITests.self).json(named: "test")
Shawshank.take(matching: .scheme("http") && .host("www.example.com")).fixture(json)
Shawshank.take { (components: URLComponents) in
    return components.host == "www.example.com" && components.port == 82
}.fixture(JSONDataFixture(["test":"json"]))

Unit Test Example

func testShawshankMatchingDataTaskRespondingWithJSONDataFixture() {
    let testRequest = URLRequest(url: URL(string: "http://www.example.com")!)
    
    Shawshank.take(matching: .scheme("http") && .host("www.example.com")).fixture(JSONDataFixture(["test":"json"]))
    
    let expect = expectation(description: "response successful")
    URLSession.shared.dataTask(with: testRequest) { (data, response, error) -> Void in
        guard let httpResponse = response as? HTTPURLResponse else { return }
        XCTAssertNil(error)
        XCTAssertEqual(httpResponse.statusCode, 200)
        XCTAssertNotNil(data)
        
        guard let data = data else { XCTFail(); return }
        guard let json = try? JSONSerialization.jsonObject(with: data, options:[]) as? Dictionary<String, String> else { XCTFail(); return }
            
        XCTAssertEqual(json?["test"], "json")
        expect.fulfill()
    }.resume()
        
    waitForExpectations(timeout: 1, handler: nil)
}

Ackowledgments

Inspiration

You can’t perform that action at this time.