【问题标题】:RSpec test PUT update actionRSpec 测试 PUT 更新操作
【发布时间】:2013-06-30 11:06:48
【问题描述】:

我正在尝试编写一些 RSpec 测试来测试我的应用程序,但我偶然发现了几个我找不到任何解决方案的问题。 1)我正在尝试测试更新操作。这是我的代码:

        it "email is a new one" do
            put :update, id: @user, user: FactoryGirl.attributes_for(:user, :email=>"a@b.c")
            @user.reload
            @user.email.should == "a@b.c"
            puts @user.email
        end

这是 UsersController 更新操作:

  def update
    @user = User.find(params[:id])
    respond_to do |format|
      if @user.update_attributes(params[:user])
        format.html { redirect_to edit_user_path(@user), :notice => "Your settings were successfully updated."}
        format.json { head :no_content }
      else
        format.html { render action: "edit" }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

这是错误:

 Failure/Error: @user.email.should == "a@b.c"
       expected: "a@b.c"
            got: "user16@example.com" (using ==)

很明显,测试并没有改变用户的电子邮件。 我从这里获取了更新操作教程:http://everydayrails.com/2012/04/07/testing-series-rspec-controllers.html。 我在哪里可以找到解决方案?

【问题讨论】:

  • 您将工厂分配给联系人,而不是用户...是这样的吗?
  • 对不起。忘记换了。为了避免错别字,我已经多次编写并复制了它。但问题依然存在。

标签: ruby-on-rails rspec crud put


【解决方案1】:

@user.update_attributes(params[:user]) 是否会因为验证原因而失败?

此外,您可以确保您的测试和控制器方法与同一个 ruby​​ 对象进行交互。过去这对我来说是一个陷阱。我这样做的方法是在类上存根 find 方法。

it "email is a new one" do
  User.stubs(:find).returns(@user)
  put :update, id: @user, user: FactoryGirl.attributes_for(:user, :email=>"a@b.c")
  @user.reload
  @user.email.should == "a@b.c"
  puts @user.email
end

这可确保您在测试期间谈论的不仅是相同的记录,而且是相同的对象。


最后,我认为你的测试对你很有帮助。您基本上是在测试update_attributes,这是一项核心功能并且已经过全面测试。我将专注于测试控制器的行为。像这样的:

let(:user) { FactoryGirl.create(:user) }

describe "PUT #update" do

  before(:each) {
    User.stubs(:find).returns(user)
  }

  it "should redirect to the user path on succesful save" do
    user.should_receive(:update_attributes).and_return true
    put :update, user, {}
    response.should redirect_to(edit_user_path(user))
  end

  it "should render the edit screen again with errors if the model doesn't save" do
    user.should_receive(:update_attributes).and_return false
    put :update, user, {}
    response.should render_template("edit")
  end
end

【讨论】:

    【解决方案2】:

    我认为put 的论点不正确。

    putgetdeletepost 接受三个参数。第一个是path,第二个是params,第三个是options。

    在您的代码中,您将两个参数作为两个参数,这是不正确的。

    put :update, id: @user, user: FactoryGirl.attributes_for(:user, :email=>"a@b.c")
    

    所以,改成

    put :update, {id: @user, user: FactoryGirl.attributes_for(:user, :email=>"a@b.c")}
    

    但是,等等!您的代码将通过上述更改工作,但您当前的代码存在安全漏洞。确保您将在控制器代码中添加权限检查。例如

    return unauthorized unless @user == current_user || current_user.role == "admin"
    

    【讨论】:

    • 谢谢!我会尽力。而且我已经修复了安全漏洞;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-02
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 2020-04-14
    • 1970-01-01
    相关资源
    最近更新 更多