【问题标题】:Why does this delete test not delete my object?为什么这个删除测试没有删除我的对象?
【发布时间】:2016-01-27 07:23:55
【问题描述】:

这是我的规范的样子:

  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

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

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

【问题讨论】:

  • 你能显示你在哪里初始化@user1
  • @TylerFerraro 我刚刚用该信息更新了问题。
  • 测试对我来说看起来不错,也许尝试抛出另一个期望语句来验证它是否重定向到 :back:root_path。测试可能会失败,因为您的用户创建语句失败或没有持久化。
  • @TylerFerraro - 是的……那行得通。我刚刚用结果更新了问题。

标签: ruby-on-rails ruby-on-rails-4 rspec rspec-rails


【解决方案1】:

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

can :destroy, User

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

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

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

编辑:

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

【讨论】:

  • 这实际上引发了另一个问题,当我运行我的规范时,我如何找出current_userid
  • 啊,你说得对,我不熟悉can :manage。你能展示你的login_user 方法吗?
  • 啊有趣。刚刚用我的login_user 方法更新了我的问题。
  • 更新我上面的答案。
  • 啊……这太完美了。解决这个问题的方法就是删除对login_user 的调用,然后执行sign_in @user1。如果您更新答案以建议我接受它。非常感谢!
【解决方案2】:

您的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

【讨论】:

  • 我刚刚更新了问题。当我修改测试以检查响应中的redirect_to 路径时,它似乎正在前往正确的位置——即root_path,只有在控制器中成功调用@user.destroy 时才会发生这种情况。所以看起来它实际上是在击中destroy 动作,还是我错过了什么?
  • 不确定是否重要,但我的控制器上唯一的 before_action 是 CanCanCan 所需的 load_and_authorize_resource。会不会是授权问题?鉴于我之前的评论中的 redirect_to root_path 作品,不确定情况是否如此。
  • 如果您将raise 语句放在destroy 操作的顶部,您会得到什么?
  • 如果你有 rescue_from CanCan::AccessDenied 重定向到 root_path 的语句,那么上面的测试看起来就像他们正在工作。试试raise,我们应该更清楚地了解发生了什么。
  • 你们俩似乎都是正确的。当我添加raise 时,测试仍然失败并且它实际上并没有引发错误。它只是像往常一样进行。如果你看这个问题,我实际上注释掉了load_and_authorize_resource 并且测试通过了。所以现在的问题是,根据我粘贴在我的问题中的ability.rb,我如何让这个测试通过?
猜你喜欢
  • 2018-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多