我在这个问题上纠结了好几天,不知道出了什么问题。我几个月前开始使用Ruby on Rails,目前正在学习使用API进行身份验证。我看过其他类似的主题here和there,但没有一个帮助。
我的问题是每当我对这段代码(位于spec/api/v1/controllers/posts_controller_spec.rb
)运行RSpec时
require 'rails_helper'
RSpec.describe Api::V1::PostsController, type: :controller do
let(:my_user) { create(:user) }
let(:my_topic) { create(:topic) }
let(:my_post) { create(:post, topic: my_topic, user: my_user) }
context "unauthenticated user" do
it "PUT update returns http unauthenticated" do
put :update, topic_id: my_topic.id, id: my_post.id, post: {title: my_post.title, body: my_post.body}
expect(response).to have_http_status(401)
end
...
字符串
我一直收到
...
spec/api/v1/controllers/posts_controller_spec.rb -e "unauthenticated user"
Run options: include {:full_description=>/unauthenticated\ user/}
FFF
Failures:
1) PostsController unauthenticated user PUT update returns http unauthenticated
Failure/Error: expect(response).to have_http_status(401)
expected the response to have status code 401 but it was 302
# ./spec/api/v1/controllers/posts_controller_spec.rb:12:in `block (3 levels) in <top (required)>'
型
如果这有帮助,我的控制器app/controllers/api/v1/posts_controller_spec.rb
有
class Api::V1::PostsController < Api::V1::BaseController
before_action :authenticate_user, except: [:index, :show]
before_action :authorize_user, except: [:index, :show]
def update
post = Post.find(params[:id])
if post.update_attributes(post_params)
render json: post.to_json, status: 200
else
render json: {error: "Post update failed", status: 400}, status: 400
end
end
...
型
我的base_controller
class Api::V1::BaseController < ApplicationController
skip_before_action :verify_authenticity_token
rescue_from ActiveRecord::RecordNotFound, with: :not_found
rescue_from ActionController::ParameterMissing, with: :malformed_request
def authenticate_user
authenticate_or_request_with_http_token do |token, options|
@current_user = User.find_by(auth_token: token)
end
end
def authorize_user
unless @current_user && @current_user.admin?
render json: {error: "Not Authorized", status: 403}, status: 403
end
end
def malformed_request
render json: {error: "The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.", status: 400}, status: 400
end
def not_found
render json: {error: "Record not found", status: 404}, status: 404
end
end
型
最后,routes.rb显示:
namespace :api do
namespace :v1 do
resources :users, only: [:index, :show, :create, :update]
resources :topics, except: [:edit, :new] do
resources :posts, only: [:update, :create, :destroy]
end
end
end
型
我有一种强烈的预感,我的before_action是罪魁祸首,但我不能指出我做错了什么。我在Topics上做过类似的事情(帖子嵌套在Topics中)使用类似的RSpec测试,我的Topic RSpec通过了,而我的Posts RSpec失败得很惨。
有人能帮我指出我做错了什么吗?我如何通过RSpec测试而不显示302状态代码?
作为一个额外的,* 为什么 * 它显示302状态代码?
3条答案
按热度按时间s4n0splo1#
问题是你在用
before_action :authenticate_user, except: [:index, :show]
,可能是Devise的助手,对吗?如果是这样的话,当你尝试在没有登录的情况下访问一个资源时,这个助手会重定向到登录页面,这是你在使用浏览器时所期望的,但这不是你的情况。你可以找到一些替代方法,覆盖Devise行为,我的解决方案是定义我的authenticate_user!
方法,如果用户没有登录,返回401,使用另一个devise helper方法,类似于这样:字符串
这个案子对我很有效,你的可能不一样。
rsaldnfx2#
我遇到了同样的问题,而正常使用
字符串
我要求的规格。
我首先尝试通过删除
auth_headers
来测试401 Unauthorized情况,然后导致意外的302 Found响应。然而,通过Postman测试我的API工作正常(401响应没有auth头)。
解决方案是删除
Authorization
头并 * 保留 *Accept
头,这样应用程序就会知道它不是在和用户对话,因此不会重定向到登录页面:型
vybvopom3#
我认为问题在于,如果请求是从浏览器发出的,design返回HTTP 302 Redirect,否则返回401 Unauthorized。
我认为解决方案是更新测试文件中的请求,看起来像这样:
字符串