测试一个用户不能 update/destroy 另一个用户的评论
Testing that a user can't update/destroy another user's comment
在我的小应用程序中,用户可以 post 发表评论。这些评论只能由其所有者销毁。我正在尝试登录用户、创建评论、注销用户,然后尝试删除第一个用户创建的评论。但是,由于某种原因,此操作成功了。这是我的评论控制器,仅显示创建和更新操作以及私有方法:
module Api
module V1
class CommentsController < Api::V1::BaseController
before_action :check_user
before_action :get_comment, only: [:destroy, :update]
respond_to :json
def destroy
if @comment.destroy
head :no_content, status: :no_content
else
render json: serialize_model(@comment.errors)
end
end
def update
if @comment.update_attributes(comment_params)
render json: serialize_model(@comment), status: :accepted
else
render json: { errors: @comment.errors }, status: :bad_request
end
end
private
def comment_params
params.require(:comment).permit(:text, :picture_id)
end
def get_comment
@comment = Comment.find_by_id(params[:id])
check_owner
end
def check_user
render json: { errors: { user: "not signed in" } }, status: :unauthorized unless user_signed_in?
end
def check_owner
render json: { errors: { user: "not the owner" } }, status: :unauthorized unless current_user.id = @comment.id
end
end
end
end
这些是我共享的测试示例:
shared_context 'comments' do
def setup_requirements_without_login
@user = FactoryGirl.create(:user)
@category = FactoryGirl.create(:category)
@picture = FactoryGirl.create(:picture, category_id: @category.id, user_id: @user.id)
end
def setup_requirements_with_login
setup_requirements_without_login
sign_in(@user)
end
shared_examples 'not the owner' do
it 'creates a resource' do
body = JSON.parse(response.body)
expect(body).to include('errors')
data = body['errors']
expect(data).to include('user')
end
it 'responds with 401' do
expect(response).to have_http_status(401)
end
end
end
这些是更新和销毁操作的测试:
需要 "rails_helper"
包括 Warden::Test::Helpers
Warden.test_mode!
RSpec.describe Api::V1::CommentsController,输入::controller do
include_context'comments'
describe 'PATCH /api/comments/:id' do
context 'when it is a valid request' do
let(:attr) do
{ text: 'update' }
end
before(:each) do
setup_requirements_with_login
@comment = FactoryGirl.create(:comment, picture_id: @picture.id, user_id: @user.id)
patch :update, id: @comment.id, comment: attr , format: :json
end
it 'creates a resource' do
body = JSON.parse(response.body)
expect(body).to include('data')
data = body['data']
expect(data['attributes']['text']).to eq('update')
end
it 'responds with 202' do
expect(response).to have_http_status(202)
end
end
context 'when the user is not logged in' do
let(:attr) do
{ text: 'update' }
end
before(:each) do
setup_requirements_without_login
@comment = FactoryGirl.create(:comment, picture_id: @picture.id, user_id: @user.id)
patch :update, id: @comment.id, comment: attr , format: :json
end
it_behaves_like "not logged in"
end
context 'when the user is not the owner' do
let(:attr) do
{ text: 'update' }
end
before(:each) do
setup_requirements_with_login
@comment = FactoryGirl.create(:comment, picture_id: @picture.id, user_id: @user.id)
sign_out(@user)
logout
@user2 = FactoryGirl.create(:user)
sign_in(@user2)
patch :update, id: @comment.id, comment: attr , format: :json
end
it_behaves_like "not the owner"
end
end
describe 'DELETE /api/comments/:id' do
context 'when it is a valid request' do
before(:each) do
setup_requirements_with_login
@comment = FactoryGirl.create(:comment, picture_id: @picture.id, user_id: @user.id)
delete :destroy, id: @comment.id, format: :json
end
it 'responds with 204' do
expect(response).to have_http_status(204)
end
end
context 'when the user is not logged in' do
before(:each) do
setup_requirements_without_login
@comment = FactoryGirl.create(:comment, picture_id: @picture.id, user_id: @user.id)
delete :destroy, id: @comment.id, format: :json
end
it_behaves_like "not logged in"
end
context 'when the user is not the owner' do
before(:each) do
setup_requirements_with_login
@comment = FactoryGirl.create(:comment, picture_id: @picture.id, user_id: @user.id)
sign_out(@user)
logout
@user2 = FactoryGirl.create(:user)
sign_in(@user2)
delete :destroy, id: @comment.id, format: :json
end
it_behaves_like "not the owner"
end
end
结束
我的问题是该操作在出于某种原因不应该成功的时候成功了。我使用 pry 进行调试,这让我更加质疑测试,因为它说 current_user 的 ID 为 97,当测试创建具有 ID 的用户时:1001 和 1002 这很奇怪......。我在控制器中犯了错误吗?或测试?
您的 check_owner
函数在其除非条件中应具有 ==
而不是 =
:
unless current_user.id == @comment.id
否则 @comment
中的 id
将分配给 current_user.id
。这可能是你 97 的起源。=)
def get_comment
@comment = current_user.comments.find! params[:id]
end
这会自动将关联添加到 SQL 查询(其中 user_id=1337),如果找不到记录,bang 方法(带有 !)将抛出 404 异常。这是控制只有所有者才能访问其自己的记录的最简单方法。
在我的小应用程序中,用户可以 post 发表评论。这些评论只能由其所有者销毁。我正在尝试登录用户、创建评论、注销用户,然后尝试删除第一个用户创建的评论。但是,由于某种原因,此操作成功了。这是我的评论控制器,仅显示创建和更新操作以及私有方法:
module Api
module V1
class CommentsController < Api::V1::BaseController
before_action :check_user
before_action :get_comment, only: [:destroy, :update]
respond_to :json
def destroy
if @comment.destroy
head :no_content, status: :no_content
else
render json: serialize_model(@comment.errors)
end
end
def update
if @comment.update_attributes(comment_params)
render json: serialize_model(@comment), status: :accepted
else
render json: { errors: @comment.errors }, status: :bad_request
end
end
private
def comment_params
params.require(:comment).permit(:text, :picture_id)
end
def get_comment
@comment = Comment.find_by_id(params[:id])
check_owner
end
def check_user
render json: { errors: { user: "not signed in" } }, status: :unauthorized unless user_signed_in?
end
def check_owner
render json: { errors: { user: "not the owner" } }, status: :unauthorized unless current_user.id = @comment.id
end
end
end
end
这些是我共享的测试示例:
shared_context 'comments' do
def setup_requirements_without_login
@user = FactoryGirl.create(:user)
@category = FactoryGirl.create(:category)
@picture = FactoryGirl.create(:picture, category_id: @category.id, user_id: @user.id)
end
def setup_requirements_with_login
setup_requirements_without_login
sign_in(@user)
end
shared_examples 'not the owner' do
it 'creates a resource' do
body = JSON.parse(response.body)
expect(body).to include('errors')
data = body['errors']
expect(data).to include('user')
end
it 'responds with 401' do
expect(response).to have_http_status(401)
end
end
end
这些是更新和销毁操作的测试: 需要 "rails_helper" 包括 Warden::Test::Helpers Warden.test_mode!
RSpec.describe Api::V1::CommentsController,输入::controller do include_context'comments'
describe 'PATCH /api/comments/:id' do
context 'when it is a valid request' do
let(:attr) do
{ text: 'update' }
end
before(:each) do
setup_requirements_with_login
@comment = FactoryGirl.create(:comment, picture_id: @picture.id, user_id: @user.id)
patch :update, id: @comment.id, comment: attr , format: :json
end
it 'creates a resource' do
body = JSON.parse(response.body)
expect(body).to include('data')
data = body['data']
expect(data['attributes']['text']).to eq('update')
end
it 'responds with 202' do
expect(response).to have_http_status(202)
end
end
context 'when the user is not logged in' do
let(:attr) do
{ text: 'update' }
end
before(:each) do
setup_requirements_without_login
@comment = FactoryGirl.create(:comment, picture_id: @picture.id, user_id: @user.id)
patch :update, id: @comment.id, comment: attr , format: :json
end
it_behaves_like "not logged in"
end
context 'when the user is not the owner' do
let(:attr) do
{ text: 'update' }
end
before(:each) do
setup_requirements_with_login
@comment = FactoryGirl.create(:comment, picture_id: @picture.id, user_id: @user.id)
sign_out(@user)
logout
@user2 = FactoryGirl.create(:user)
sign_in(@user2)
patch :update, id: @comment.id, comment: attr , format: :json
end
it_behaves_like "not the owner"
end
end
describe 'DELETE /api/comments/:id' do
context 'when it is a valid request' do
before(:each) do
setup_requirements_with_login
@comment = FactoryGirl.create(:comment, picture_id: @picture.id, user_id: @user.id)
delete :destroy, id: @comment.id, format: :json
end
it 'responds with 204' do
expect(response).to have_http_status(204)
end
end
context 'when the user is not logged in' do
before(:each) do
setup_requirements_without_login
@comment = FactoryGirl.create(:comment, picture_id: @picture.id, user_id: @user.id)
delete :destroy, id: @comment.id, format: :json
end
it_behaves_like "not logged in"
end
context 'when the user is not the owner' do
before(:each) do
setup_requirements_with_login
@comment = FactoryGirl.create(:comment, picture_id: @picture.id, user_id: @user.id)
sign_out(@user)
logout
@user2 = FactoryGirl.create(:user)
sign_in(@user2)
delete :destroy, id: @comment.id, format: :json
end
it_behaves_like "not the owner"
end
end
结束
我的问题是该操作在出于某种原因不应该成功的时候成功了。我使用 pry 进行调试,这让我更加质疑测试,因为它说 current_user 的 ID 为 97,当测试创建具有 ID 的用户时:1001 和 1002 这很奇怪......。我在控制器中犯了错误吗?或测试?
您的 check_owner
函数在其除非条件中应具有 ==
而不是 =
:
unless current_user.id == @comment.id
否则 @comment
中的 id
将分配给 current_user.id
。这可能是你 97 的起源。=)
def get_comment
@comment = current_user.comments.find! params[:id]
end
这会自动将关联添加到 SQL 查询(其中 user_id=1337),如果找不到记录,bang 方法(带有 !)将抛出 404 异常。这是控制只有所有者才能访问其自己的记录的最简单方法。