带Devise的第5轨,使用Rspec测试控制器(破坏行为)

问题描述 投票:1回答:2

我正在为destroy操作实施rspec测试,其概念是已登录的用户只能销毁自己的帖子,而不能销毁其他用户创建的帖子。

The `new_post` is created by a user named `creator`, and another user named `user1` signed in and try to delete the `new_post`, it should not be able to delete it, because of the `  before_action :authenticate_user!, only: %i[create destroy]` in Posts controller

Posts controller。

class PostsController < ApplicationController
  before_action :set_post, only: %i[show edit update destroy]
  before_action :current_user, only: %i[create destroy]
  before_action :authenticate_user!, only: %i[create destroy]
  .
  .
  .

  def destroy
    @post.destroy
    respond_to do |format|
      format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private

  def set_post
    @post = Post.find(params[:id])
  end


  def post_params
    params.require(:post).permit(:content, :picture)
  end
end

用户控制器规格

require 'rails_helper'
RSpec.describe PostsController, type: :controller do
  context  'DELETE #destroy' do

    let(:user1) {User.create!(name:"John", email:"[email protected]", password:"password")}

    let(:creator) { User.create!(name: "creator", email: "[email protected]", password: "password") }

    let(:new_post){creator.posts.create!(content: "Neque porro quisquam est qui dolorem ipsum")}


    it 'A user cannot delete a post created by other user' do
      sign_in user1
      p (new_post)
      expect { delete :destroy, params: { id: new_post.id } }.to change(Post, :count).by(0)

    end
  end
end

失败:

  1) PostsController DELETE #destroy A user cannot delete a post created by other user
     Failure/Error: expect { delete :destroy, params: { id: new_post.id } }.to change(Post, :count).by(0)
       expected `Post.count` to have changed by 0, but was changed by -1
ruby ruby-on-rails-5 factory-bot rspec-rails
2个回答
2
投票

我相信您需要在代码中添加授权支票。authenticate_user!authenticates发出请求的人已登录。但是,它不会检查用户是否具有authorized来发出他们正在发出的请求。

请参阅Authentication versus Authorization,对这两个概念进行更多讨论。并查看https://stackoverflow.com/a/25654844/868533,以很好地概述Rails中流行的授权gem。需要明确的是,您几乎肯定需要一种方法来验证用户(Devise)以及授权gem。

假设您决定使用CanCanCan(这是我过去使用的常见选项),您将添加一个Ability类,例如:

class Ability
  include CanCan::Ability

  def initialize(user)
    if user.present?
      can :destroy, Post, user_id: user.id
    end
  end
end

然后,您可以在控制器上将before_action :check_authorization, only: %i[destroy]添加为新的before_action,并且测试应通过且无需进行任何修改。


1
投票

记住。您正在编写控制器测试。因此此测试为unit testDevise中有两种主要的授权方法。它们是授权路由和授权控制器。如果使用授权路由,则在为控制器编写rspec时,必须使用stub伪造授权访问。

© www.soinside.com 2019 - 2024. All rights reserved.