为什么这个删除测试不删除我的对象?

Why does this delete test not delete my object?

这是我的规格:

  it "should successfullly destroy that user record" do
    expect {
      delete :destroy, :id => @user1.id
    }.to change{User.count}.by(-1)
  end

在我的 UsersController

中调用此操作
  def destroy
    @user = User.find(params[:id])
    if @user.destroy
      redirect_to root_path, notice: "You have successfully cancelled your account."
    else
      redirect_to :back
    end
  end

但是当我 运行 那个规格时,我得到这个:

RSpec::Expectations::ExpectationNotMetError: expected result to have changed by -1, but was changed by 0

我该如何解决这个问题?

编辑 1

@user1 正在 it 语句所在的 context 块顶部的 before_each 调用中初始化。看起来像这样:

context "when the inviter is being deleted and invited has not accepted invitation" do
  before :each do
    @user1 = create(:user, gender: 0)
    @user2 = create(:user)
    @member = create(:member, email: @user2.email, first_name: @user2.first_name, last_name: @user2.last_name, bio: @user2.bio, gender: @user2.gender)
    @membership = create(:membership, member: @member, family_tree: @user1.family_tree, inviter: @user1, relation: "sister")
    @connection = create(:connection, inviter_membership: @membership)
    login_user
  end

编辑 2

当我用这个替换测试时,它有效:

  it "should successfullly destroy that user record" do
    delete :destroy, id: @user1
    expect(response).to redirect_to(root_path)
    # expect {
    #   delete :destroy, id: @user1
    # }.to change(User,:count).by(-1)
  end

测试成功通过。

Finished in 1.2 seconds (files took 6.08 seconds to load)
19 examples, 0 failures, 15 pending

编辑 3

为了它的价值,在我的 UsersController 中,我在顶部调用 load_and_authorize_resource。当我删除它时,测试似乎确实通过了。所以问题是,如何让它与 CanCanCan 一起使用?

这是我的 ability.rb 的样子:

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user (not logged in)
    if user.has_role? :admin
      can :manage, :all
    end

    can :manage, FamilyTree, user_id: user.id
    can :manage, Comment, user_id: user.id
    can :manage, Node, user_id: user.id
    can :manage, Event, user_id: user.id
    can :manage, User, id: user.id

    can :read, Comment, user_id: user.id
    can :read, Event, user_id: user.id
  end
end

编辑 4

当我将 raise 添加到我的 destroy 操作时...没有任何反应。所以看来我的 destroy 操作确实没有被执行。

编辑 5

这就是我的 login_user 方法的样子:

module SpecAuthentication
  def login_user
    @request.env["devise.mapping"] = Devise.mappings[:user]
    @user = FactoryGirl.create :user
    sign_in @user
  end
end

你的 destroy action 没有受到 spec 的影响,检查是否有某种 before_action 阻止它这样做。

我会这样做:

  def destroy
    raise # The action was hit
    @user = User.find(params[:id])
    if @user.destroy
      redirect_to root_path, notice: "You have successfully cancelled your account."
    else
      redirect_to :back
    end
  end

使用 CanCanCan gem 您必须允许控制器操作。您需要将其添加到您的 ability.rb 文件中。

can :destroy, User

这将允许具有该角色的任何人销毁用户对象。您可以添加更多细节以适合您的用例。

编辑:刚看到关于 CanCanCan gem 的 :manage 文档。

您的能力文件目前允许用户自行管理。您的 login_user 方法正在动态创建一个用户,而您的测试试图销毁一个单独的用户。您可以更新您的 CanCan 能力,让所有用户都被销毁,或者假设您有 current_user 方法,尝试销毁 current_user.id。我强烈建议更改您的 login_user 方法以接受用户对象,以便您知道哪个用户已登录并可以访问该对象。

编辑:

如上所述,使用一种方法 sign_in 特定用户,以便您可以将其作为对象进行访问。将 login_user 调用替换为 sign_in @user1 或接受用户对象的类似方法。