【问题标题】:Testing that a user can't update/destroy another user's comment测试用户不能更新/销毁其他用户的评论
【发布时间】:2015-08-22 10:37:16
【问题描述】:

在我的小应用程序中,用户可以发布 cmets。这些 cmets 只能由其所有者销毁。我正在尝试登录用户,创建评论,注销用户,然后尝试删除第一个用户创建的评论。但是,由于某种原因,此操作成功了。这是我的 cmets 控制器,仅显示创建和更新操作以及私有方法:

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, type: :controller do include_context 'cmets'

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,这很奇怪......我在控制器中犯了错误吗?还是测试?

【问题讨论】:

    标签: ruby-on-rails rspec devise


    【解决方案1】:

    您的 check_owner 函数在其除非条件中应包含 == 而不是 =

    unless current_user.id == @comment.id
    

    否则来自@commentid 将分配给current_user.id。这可能是你 97 的由来。=)

    【讨论】:

    • 我会尽快接受答案。它应该是 @comment.user_id 哦上帝。我的头很轻
    【解决方案2】:
      def get_comment
        @comment = current_user.comments.find! params[:id]
      end
    

    这会自动将关联添加到 SQL 查询(其中 user_id=1337),如果找不到记录,bang 方法(带有 !)会抛出 404 异常。这是控制只有所有者才能访问自己的记录的最简单方法。

    【讨论】:

    • 哦,好主意。谢谢!
    猜你喜欢
    • 2019-12-08
    • 2018-11-06
    • 1970-01-01
    • 2019-04-15
    • 2012-05-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-26
    • 2016-09-05
    相关资源
    最近更新 更多