新泽西州最大的新手提出的 RSpec2 错误:( |factory_girl, authlogic,rails3

发布于 2024-09-18 01:59:15 字数 1748 浏览 3 评论 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 "[email protected]"
  u.single_access_token "k3cFzLIQnZ4MHRmJvJzg"
  u.id "37"
end

I'm writing an rspec scenario thats failing with:

 (#<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 - factories

Factory.define :valid_user, :class => User do |u|
  u.username "Trippy"
  u.password "password"
  u.password_confirmation "password"
  u.email "[email protected]"
  u.single_access_token "k3cFzLIQnZ4MHRmJvJzg"
  u.id "37"
end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

太阳男子 2024-09-25 01:59:16

Authlogic 的标准帮助器方法(例如 current_user)不会直接调用 User.find。我相信它会 current_user_session.user,其中 current_user_session 调用 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

Authlogic's standard helper methods like current_user don't call User.find directly. I believe it does current_user_session.user, where current_user_session calls UserSession.find, so you're not calling User.find directly. You could do some fancy chain stubbing there, but my suggestion is just to add this to your controller spec instead of what you're currently stubbing:

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

In RSpec2 you might have to do

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

Edit: This should be your whole spec file:

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
贩梦商人 2024-09-25 01:59:16

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

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 > 过滤器已重定向请求。

I think you're confusing stubs with message expectations. The line

User.should_receive(:find)

tells Rspec to expect the User model to receive a find message. Whereas:

User.stub!(:find)

replaces the find method so that the test can pass. In your example the thing you're testing is whether update_attributes is called successfully, so that ought to be where the message expectation goes, and the job of all the other testing code is just to set up the prerequisites.

Try replacing that line with:

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

Note that find returns the object, not just its id. Also, note that stubbing out find here serves only to speed things up. As written the example gets through should_receive(:find) successfully, and that is happening because you're using Factories to create users in the test database. You could take the stub out and the test should still work, but at the cost of hitting the database.

Another tip: if you're trying to figure out why a controller test isn't working, sometimes it's helpful to know if it is being blocked by before filters. You can check for this with:

controller.should_receive(:update)

If that fails, the update action is not being reached, probably because a before filter has redirected the request.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文