0

我正在编写一个失败的 rspec 场景:

 (#<User:0x1056904f0>).update_attributes(#<RSpec::Mocks::ArgumentMatchers::AnyArgMatcher:0x105623648>)
     expected: 1 time
     received: 0 times

users_controller_spec.rb:

describe "Authenticated examples" do
  before(:each) do
    activate_authlogic
    @user = Factory.create(:valid_user)
    UserSession.create(@user)
  end

describe "PUT update" do
    it "updates the requested user" do
      User.stub!(:current_user).and_return(@user)
      @user.should_receive(:update_attributes).with(anything()).and_return(true)
      put :update, :id => @user , :current_user => {'email' => 'Trippy'}
      puts "Spec Object Id : " + "#{@user.object_id}"
 end

users_controller.rb:

def update
  @user = current_user
  puts "Controller Object ID is : " + "#{@user.object_id}"

  respond_to do |format|
    if @user.update_attributes(params[:user])
      format.html { redirect_to(root_url, :notice => 'Successfully updated profile.') }
      format.xml  { head :ok }
    else
      format.html { render :action => "edit" }
      format.xml  { render :xml => @user.errors, :status => :unprocessable_entity }
    end
  end
end

user.rb - 工厂

Factory.define :valid_user, :class => User do |u|
  u.username "Trippy"
  u.password "password"
  u.password_confirmation "password"
  u.email "elephant@gmail.com"
  u.single_access_token "k3cFzLIQnZ4MHRmJvJzg"
  u.id "37"
end
4

2 回答 2

2

我认为您将存根与消息期望混淆了。线

User.should_receive(:find)

告诉 Rspec 期望 User 模型收到一条查找消息。然而:

User.stub!(:find)

替换 find 方法以便测试可以通过。在您的示例中,您要测试的是是否update_attributes被成功调用,因此这应该是消息期望所在的位置,而所有其他测试代码的工作只是设置先决条件。

尝试将该行替换为:

User.stub!(:find).and_return(@user)

请注意,它find返回对象,而不仅仅是它的 id。另外,请注意,find这里的存根只是为了加快速度。正如所写的示例should_receive(:find)成功通过,是因为您使用工厂在测试数据库中创建用户。您可以取出存根,测试应该仍然有效,但代价是访问数据库。

另一个提示:如果您试图找出控制器测试不起作用的原因,有时了解它是否被before过滤器阻止会很有帮助。您可以通过以下方式检查:

controller.should_receive(:update)

如果失败,update则无法执行操作,可能是因为before过滤器重定向了请求。

于 2010-09-09T18:43:15.077 回答
2

Authlogic 的标准辅助方法,例如current_userUser.find直接调用。我相信确实如此current_user_session.user, where current_user_sessioncalls UserSession.find,所以你没有User.find直接打电话。你可以在那里做一些花哨的链存根,但我的建议只是将它添加到你的控制器规范中,而不是你当前的存根:

stub!(:current_user).and_return(@user)

在 RSpec2 中你可能需要做

controller.stub!(:current_user).and_return(@user)

编辑:这应该是你的整个规范文件:

describe "Authenticated examples" do
  before(:each) do
    activate_authlogic
    @user = Factory.create(:valid_user)
    UserSession.create(@user)
  end

describe "PUT update" do

  describe "with valid params" do
    it "updates the requested user" do
      stub!(:current_user).and_return(@user)
      @user.should_receive(:update_attributes).with(anything()).and_return(true)
      put :update, :id => @user , :current_user => {'email' => 'Trippy'}
    end
 end
于 2010-09-09T21:07:03.883 回答