Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Rails Rspec API Testing Notes

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.

@spec/supports/api_helper.rb


module ApiHelper
  include Rack::Test::Methods

  def app
    Rails.application
  end
end

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

Enable Spec_helper supports

@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

@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",:formate =>: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.

@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
@andyw8

This comment has been minimized.

Copy link

andyw8 commented Apr 28, 2015

I assume Rake::Test::Methods is supposed to be Rack::Test::Methods? (used in several places).

@tylercollier

This comment has been minimized.

Copy link

tylercollier commented Aug 8, 2015

I agree with andyw8's comments about Rack vs Rake.

@mdkalish

This comment has been minimized.

Copy link

mdkalish commented Oct 9, 2015

Did you even test code you put in this gist?

@jgonzalezd

This comment has been minimized.

Copy link

jgonzalezd commented May 9, 2017

@mdkalish, I dont think so get "/api/v1/items/1",:formate =>:json

@zx1986

This comment has been minimized.

Copy link

zx1986 commented Jun 29, 2017

In https://gist.github.com/alex-zige/5795358#enable-spec_helper-supports
It should be Rails.root.join("spec/supports/**/*.rb") ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.