如何使用RSpec测试我的更新操作?

时间:2013-06-23 17:05:23

标签: ruby-on-rails ruby-on-rails-3 rspec rspec2 rspec-rails

在我的Rails应用程序中,我有更新操作:

class UsersController < ApplicationController

  before_filter :authorized_user

  def update
    current_email = @user.email
    new_email = params[:user][:email].downcase.to_s
    if @user.update_attributes(params[:user])    
      if new_email != current_email
        @user.change_email(current_email, new_email)     
        flash[:success] = "Please click on the link that we've sent you."
      else
        flash[:success] = "User updated."
      end
      redirect_to edit_user_path(@user)
    else
      render :edit
    end
  end

  private

  def authorized_user
    @user = User.find(params[:id])
    redirect_to(root_path) unless current_user?(@user)
  end

end

class User < ActiveRecord::Base

  def change_email(old_email, new_email)
    self.email = old_email
    self.new_email = new_email.downcase    
    self.send_email_confirmation_link  
  end

end

现在,当我在浏览器中手动测试更新操作时,一切正常。

我写的 RSpec 测试不起作用,我无法弄清楚原因:

it "changes @user's new_email" do
  @user = create(:user, email: "john@doe.com")
  put :update, id: @user, user: attributes_for(:user, email: "new@email.com")
  @user.reload
  expect(@user.new_email).to eq("new@email.com")
end

我一直收到同样的错误消息:

  

1)UsersController用户访问PUT #update,有效属性更改@ user的new_email        失败/错误:期待(@ user.new_email).to eq(“new@email.com”)

   expected: "new@email.com"
        got: nil

   (compared using ==)

有人可以告诉我这里缺少什么吗?

感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

我认为你有一个错字

expect(@user.email).to eq("new@email.com")

您没有在change_email中保存用户,并且您正在更新控制器中的email。因此,代码中未更新new_email

要保存记录,请使用

def change_email(old_email, new_email)
  self.email = old_email
  self.new_email = new_email.downcase 
  save
  self.send_email_confirmation_link  
end

回调

可能是这样的:

# controller
if @user.update_attributes[:user]
  redirect_to somewhere
else
  render :edit

# model
after_update :change_email

但是有更多的变化,这只是一个模式。

无论如何,也许您应该在模型中使用回调,而不是在控制器中编写更多代码。

答案 1 :(得分:0)

您的控制器存在一些问题。

首先,您尚未定义@user。这就是你的结果为零的原因

# Define it
@user = User.find(params[:id]) # if your url is POST /user/1/update

其次,最好不要仅使用email,如果您希望允许用户进一步编辑其他属性,请说生日等等?

第三,更新用户属性比其他人有点棘手,用户必须有权这样做。考虑到一个用户在浏览器中操作表单属性并发布给另一个用户update,会发生什么?

因此,您必须检查用户是否可以这样做。

结合在一起:

def update
  @user = User.find(params[:id])
  if @user != current_user
    return redirect_to(:back, alert: "not allowed to edit")
  end

  attrs = params[:user]

  if @user.update_attributes attrs
     //do something
  else
     render { action 'edit' }
  end
end