Easily stub out HTTP responses in RubyMotion specs
Ruby
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
lib
spec
.gitignore
.travis.yml
Gemfile
Guardfile
LICENSE
README.md
Rakefile
webstub.gemspec

README.md

WebStub Code Climate Travis Gem Version

What if WebMock and NSURLProtocol had a baby?

Features

  • Supports most any HTTP library that is built on NSURLConnection / NSURLSession
  • Request matching based upon HTTP method, URI, and body
  • Optionally, disable real network access
  • Familiar, delicious syntax
  • Bacon integration

Installation

Update your Gemfile:

gem "webstub"

Bundle:

$ bundle install

Usage

  • Add the following line to the top-most describe block in your spec:

    extend WebStub::SpecHelpers

  • Use the following methods to control the use of request stubbing:

    • disable_network_access!
    • enable_network_access!
    • stub_request
    • reset_stubs

Example Spec

describe "Example" do
  extend WebStub::SpecHelpers

  describe "Stubbing a GET request to return a simple response after a delay" do
    it "retrieves the front page" do
      stub_request(:get, "http://example.com/").
        to_return(body: "Hello!", content_type: "text/plain", delay: 0.3)

      @body = nil
      @api.get_index do |body, error|
        @body = body
        resume
      end

      wait_max 1.0 do
        @body.should.be == "Hello!"
      end
    end
  end

  describe "Stubbing a GET request to return JSON" do
    it "retrieves suggestions" do
      stub_request(:get, "https://example.com/suggestions?q=mu").
        to_return(json: { suggestions: ["muse"] })

      @suggestions = nil
      @api.get_suggestions("mu") do |results, error|
        @suggestions = results
        resume
      end

      wait_max 1.0 do
        @suggestions.should.not.be.empty
      end
    end
  end

  describe "Stubbing a POST request to return JSON" do
    it "handles a POST request" do
      stub_request(:post, "https://example.com/action").
        with(body: { q: "unsustainable" }).
        to_return(json: [ { album: "The 2nd Law", release_date: "2012-10-01", artist: "Muse" } ])

      @results = nil
      @api.get_album_info_for_track("unsustainable") do |results, error|
        @results = results
        resume
      end

      wait_max 1.0 do
        @results.should.not.be.empty
      end
    end
  end

  describe "Stubbing a GET request to fail" do
    it "returns an NSError with the NSURLError domain" do
      stub_request(:get, "https://example.com/action").
        to_fail(code: NSURLErrorNotConnectedToInternet)

      @error = nil
      @api.get_albums do |results, error|
        @error = error
        resume
      end

      wait_max 1.0 do
        @error.code.should == NSURLErrorNotConnectedToInternet
      end
    end
  end
end

Conventions

  • The URL is matched exactly as is right now (hence query parameters need to be included and encoded)
  • The with method's body option accepts either a Hash or a String:
    • Hashes are assumed to be form data (with a application/x-www-form-urlencoded content type)
    • Strings are matched as is
  • The to_return method accepts a few options:
    • json: accepts either a Hash, Array or a String. If a Hash or Array is provided, it will be converted to JSON. Strings are returned as is, with the Content-Type set to application/json.
    • body: accepts a String, and returns it as-is
    • content_type: sets the Content-Type when using the body parameter
    • status_code: sets the integer Status Code of the response. Defaults to 200.
  • The to_redirect method accepts:
    • url: String of the URL to redirect to (required)
    • All options supported by to_return except for status_code
  • The to_fail method accepts one of the following options:
    • code: NSURLErrorDomain error code
    • error: NSError to fail the request with

Expectations

Sometimes, you may just want to check that the request has been made to a given URL. In this case, you can use the requested? method of the stub returned by stub_request:

describe Elevate::HTTP do
  extend WebStub::SpecHelpers

  describe ".get" do
    it "synchronously issues a HTTP GET request" do
      stub = stub_request(:get, "http://www.example.com/")

      Elevate::HTTP.get("http://www.example.com/")

      stub.should.be.requested
    end
  end
end

Callbacks

Sometimes, you may want to inspect the request made for a given URL. In this case, you can use the with_callback method of the stub returned by stub_request to add a callback hook:

describe Elevate:HTTP do
  extend WebStub::SpecHelpers

  describe ".post" do
    it "synchronously issues an HTTP POST request" do
      stub = stub_request(:post, "http://www.example.com/")

      stub.with_callback do |headers, body|
        headers.kind_of?(Hash).should == true
        body.kind_of?(Hash).should == true
        body.should == {"key" => "value"}
      end

      Elevate::HTTP.post("http://www.example.com/", json: {key: "value"})
    end
  end
end


Caveats

While WebStub supports NSURLSession, it does not support background sessions, as they don't allow the use of custom NSURLProtocol classes.

TODO

  • Handle query params similarly to form data