集成使用devise_token_auth测试rails API以进行身份​​验证,并使用Rspec

时间:2016-01-12 19:00:27

标签: ruby-on-rails rspec devise rails-api cancancan

我有一个rails-api应用程序,我正在使用Rspec进行测试。该应用程序使用devise_token_auth gem进行身份验证,使用cancancan gem进行授权。

devise_token_auth要求客户端在每个请求中包含这些身份验证标头: access-tokenclientexpiryuid。使用emailpassword成功进行身份验证后,这些标头在响应中可用。

我决定使用this answer中提供的解决方案在测试期间设置这些标头。

ability.rb我有这个:

## models/ability.rb

class Ability
  include CanCan::Ability

  def initialize(user)
   if user.role? :registered
     can :create, Post, user_id: user.id
     can :update, Post, user_id: user.id
     can :destroy, Post, user_id: user.id
     can :read, Post
   end
  end
end 
posts#show中的

PostsController操作如下所示:

## controllers/posts_controller.rb

class PostsController < ApplicationController
  before_action :authenticate_user!
  load_and_authorize_resource

  def show
    render json: @post
  end
end

我已经救出了CanCan::AccessDenied错误,在403

中呈现了json消息,状态为forbidden ApplicationController
rescue_from CanCan::AccessDenied do |exception|
  render json: {"message" => "unauthorized"}.to_json, :status => 403
end

我在spec/support/session_helper.rb

中有这个
module SessionHelper
 def retrieve_access_headers

 ##I have a user with these credentials and has a "registered" role. in the the test db.

   post "/auth/sign_in", params: {:email => "registered_user@gmail.com", :password => "g00dP@ssword"}, headers: {'HTTP_ACCEPT' => "application/json"}

##These two pass
expect(response.response_code).to eq 200
expect(response.body).to match(/"email": "registered_user@gmail.com"/)

     access_headers = {"access-token" => response.headers["access-token"],
     "client" => response.headers["client"],
     "expiry" => response.headers["expiry"],
     "uid" => response.headers["uid"],
     "token-type" => response.headers["token-type"],
     'HTTP_ACCEPT' => "application/json"
   }

  return access_headers
 end

我在spec/support/requests_helper.rb

中有这个
module RequestsHelper
  def get_with_token(path, params={}, headers={})
   headers.merge!(retrieve_access_headers)
   get path, params: params, headers: headers

   #### this outputs the expected headers on a json string and they seem fine ####
   puts "headers: "+headers.to_json
  end
end

我已在rails_helper.rb中加入了两位助手,如下所示:

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

RSpec.configure do |config|
   config.include SessionHelper, type: :request
   config.include RequestsHelper, type: :request
end

最后,我在spec/request/posts/show_spec.rb

中有一个请求规范
require 'rspec/its'
require 'spec_helper'
require 'rails_helper'

RSpec.describe 'GET /posts/:id', :type => :request do

    let(:post) {create(:post)}
    let(:id) {post.id}
    let(:request_url) {"/posts/#{id}"}

  context 'with a registered user' do
   it 'has a status code of 200' do
     get_with_token request_url
     expect(response).to have_http_status(:success)
   end
  end
end

我希望这会通过,但它会失败并显示消息:

Failure/Error: expect(response).to have_http_status(:success)
   expected the response to have a success status code (2xx) but it was 403

应用程序在浏览器上按预期工作。

我做错了什么?

0 个答案:

没有答案