新泽西州最大的新手提出的 RSpec2 错误:( |factory_girl, authlogic,rails3
我正在编写一个失败的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Authlogic 的标准帮助器方法(例如
current_user
)不会直接调用User.find
。我相信它会current_user_session.user
,其中current_user_session
调用UserSession.find
,因此您不会调用User.find 直接。您可以在那里做一些奇特的链存根,但我的建议只是将其添加到您的控制器规范中,而不是您当前正在存根的内容:
在 RSpec2 中,您可能必须执行
编辑:这应该是您的整个规范文件:
Authlogic's standard helper methods like
current_user
don't callUser.find
directly. I believe it doescurrent_user_session.user
, wherecurrent_user_session
callsUserSession.find
, so you're not callingUser.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:In RSpec2 you might have to do
Edit: This should be your whole spec file:
我认为您将存根与消息期望混淆了。 行
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 outfind
here serves only to speed things up. As written the example gets throughshould_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 abefore
filter has redirected the request.