Skip to content

Instantly share code, notes, and snippets.

@helabed
Forked from alex-zige/gist:5795358
Last active August 29, 2015 14:24
Show Gist options
  • Save helabed/c65084ab7938e437283f to your computer and use it in GitHub Desktop.
Save helabed/c65084ab7938e437283f to your computer and use it in GitHub Desktop.

Rails Rspec APIs Testing Notes

Folders Structure

  spec
  |--- apis #do not put into controllers folder. 
        |--- your_api_test_spec.rb  
  |--- controllers
  |--- models
  |--- factories
  |--- views
  |--- helpers
  |--- supports
        |--- api_helper.rb
        |--- authentication_helper.rb
  |--- spec_helper.rb

*note: do not put your apis folder underneath controllers folder, otherwise, it will inherited with controller ActionController::TestCase::Behavior, Rake::Test::Methods cannot be apply accordingly.

Custom Rspec Helper for Rake::Test::Methods for api scopes.

in file spec/supports/api_helper.rb


module Rspec::ApiHelpers
  include Rack::Test::Methods

  def app
    Rails.application
  end
end

RSpec.configure do |config|
  config.include Rspec::ApiHelpers, :type=>:api #apply to all spec for apis folder
end

Enable Spec_helper supports

in file spec/spec_helper.rb
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

API Test Spec

make sure your sample test group has type: api, then it will include Rake::Test::Methods for (get,post,put,delete) requests

in file spec/apis/authentication_spec.rb

require "spec_helper"

describe "API authentication" , :type => :api do

  let!(:user) { FactoryGirl.create(:user) }

  it "making a request without cookie token " do
    get "/api/v1/items/1",:format =>:json
    last_response.status.should eql(401)
    error = {:error=>'You need to sign in or sign up before continuing.'}
    last_response.body.should  eql(error.to_json)
  end

end  

ActionController::TestCase::Behavior v.s. Rack::Test::Methods

Rspec-Rails includes ActionController::TestCase::Behavior for simulating controller requests.

so you could do

require "spec_helper"

describe Api::V1::SessionsController , :type => :api do

  let!(:user) { FactoryGirl.create(:user) }

  it "making a request without cookie token " do
    get :index
    response.status.should eql(401)
    error = {:error=>'You need to sign in or sign up before continuing.'}
    response.body.should  eql(error.to_json)
  end

end  

Points of differents:

  • Rake::Test::Methods could query the url "/api/v1/xxxx", but ActionController::TestCase::Behavior only execute actions within current controller scope.
  • the reponse in Rake::Test::Methods called: last_response, in ActionController::TestCase::Behavior called: response.

*Notes, if you change your spec/apis folder to api, you will find out the last_repsonse is not working any more. That's because the :type=> :api scope got mixed with default ActionController behavior.

A Step Further

Reusable Sign in Helper.

in file spec/supports/authentication_helper.rb

module AuthenticationHelper
  def sign_in_as_a_valid_user
      @user ||= FactoryGirl.create(:user)
      @user.reset_authentication_token! unless @user.authentication_token
      set_cookie "authentication_token=#{@user.authentication_token}"
    end
end

RSpec.configure do |config|
  config.include AuthenticationHelper, :type=>:api
end

*Notes: The Example above used token based cookie authentication. So you could change to base-authen or token-based auth based on your own needs.

Created a signed in user in your Test

use before_each or before_all block or include the helper method into your assertion block

require "spec_helper"

describe "API Items Controller", :type => :api do

  before :each do
    sign_in_as_a_valid_user
  end
  
  it "fetch all items" do
  #or include the helper method here
  sign_in_as_a_valid_user
  ...
  end
end
@helabed
Copy link
Author

helabed commented Jul 10, 2015

ApiHelper is now Rspec::ApiHelpers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment