I''m doing RSpec controller testing with CanCan authorization, and I''m seeing something I''ve never seen in RSpec before: the same test run twice fails on the second one. I am NOT doing before(:all) or other things that should cause state to persist between tests: Here''s the relevant code: context "POST create" do context "with user logged in" do before(:each) do @user = mock_model(User, :admin? => false, :guest? => false) controller.stub(:current_user) { @user } # aka login @attributes = valid_attributes end # succeeds it "should create a new Premise" do lambda{ post(:create, {:premise => @attributes}, :format => :json) }.should change(Premise, :count).by(1) end # fails with CanCan::AccessDenied it "should create a new Premise again" do lambda{ post(:create, {:premise => @attributes}, :format => :json) }.should change(Premise, :count).by(1) end end I can''t figure out why the first test passes and the second test fails -- this suggests that there''s some state that''s being preserved across the tests, but I can''t imagine what that might be, nor how to check for it. Any suggestions? (Of course, I can provide full model and Ability class info if it would be helpful.) TIA. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
UPDATE: I noticed that I had a "rails console --sandbox" running in another window. When I quit that, the behavior of the test changed. Dramatically. I haven''t sorted through the new errors, but it''s clear that the --sandbox process was causing the db to respond differently. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
MORE UPDATE: I beefed up the tests to look at the return code, the # of Premises generated and the assignment. And things only got stranger: context "POST create" do context "with user logged in" do before(:each) do @user = mock_model(User, :admin? => false, :guest? => false) controller.stub(:current_user) { @user } # aka login @attributes = valid_attributes end it "should create a new Premise" do count = Premise.count post(:create, {:premise => @attributes}, :format => :json) Premise.count.should == count + 1 response.message.should == "OK" assigns(:premise).should be_instance_of(Premise) end it "should create a new Premise again" do count = Premise.count post(:create, {:premise => @attributes}, :format => :json) Premise.count.should == count + 1 response.message.should == "OK" assigns(:premise).should be_instance_of(Premise) end end end NOW what happens: - the first test fails with response.message = "Not Acceptable" - the second test fails because count is not incremented. Why should there be any difference between the two? -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On 6 April 2012 01:10, Fearless Fool <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> MORE UPDATE: I beefed up the tests to look at the return code, the # of > Premises generated and the assignment. And things only got stranger: > > > context "POST create" do > > context "with user logged in" do > before(:each) do > @user = mock_model(User, :admin? => false, :guest? => false) > controller.stub(:current_user) { @user } # aka login > @attributes = valid_attributes > end > > it "should create a new Premise" do > count = Premise.count > post(:create, {:premise => @attributes}, :format => :json) > Premise.count.should == count + 1 > response.message.should == "OK" > assigns(:premise).should be_instance_of(Premise) > end > > it "should create a new Premise again" do > count = Premise.count > post(:create, {:premise => @attributes}, :format => :json) > Premise.count.should == count + 1 > response.message.should == "OK" > assigns(:premise).should be_instance_of(Premise) > end > > end > end > > NOW what happens: > > - the first test fails with response.message = "Not Acceptable" > - the second test fails because count is not incremented.First look in test.log to see if there is any difference there, if still no joy then debug the create action to see what is going on. Look at the Rails Guide on Debugging if you don''t know how to do this. Colin -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Colin Law wrote in post #1055228:> On 6 April 2012 01:10, Fearless Fool <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote: >> - the first test fails with response.message = "Not Acceptable" >> - the second test fails because count is not incremented. > > First look in test.log to see if there is any difference there, if > still no joy then debug the create action to see what is going on. > Look at the Rails Guide on Debugging if you don''t know how to do this. > > ColinColin, thanks. To be clear, it appears that the #create method is actually working. For the moment, I''m going to assume the first test is okay and that the "Not Acceptable" response is an issue to chase down later. I see what''s going on, but not how to fix the test: In the first test, current_user.id = 1001. Ability#new gets called and sets up the appropriate abilities. On the second test, current_user.id = 1002, but Ability#new doesn''t get called. (Is it cached?) When it tries to create a premise object, CanCan''s load_and_authorize_resource method creates a Premise with user_id = 1001, which subsequently fails because current_user''s id = 1002. So the short question: Why isn''t Ability#new getting called in every test? Or what must I do to set up the abilities? You can stop reading here if you understand the question. :) Gory details follow: My Abilities class has (effectively): # file: app/models/ability.rb class Ability def initialize(user) can :manage, Premise, :user_id => user.id end end meaning that access to a Premise is limited to its owner. My PremisesController has: # file: app/controllers/premises_controller.rb class PremisesController < ApplicationController load_and_authorize_resource respond_to :json def create @premise.save! respond_with @premise end end In the first test: current_user.id = 1001 Ability#new gets called with current_user arguments to Premise#initialize = {:user_id => 1001, ...} In the second test: current_user.id = 1002 Ability#new does NOT get called arguments to Premise#initialize = {:user_id => 1001, ...} ... which leads to a CanCan::AccessDenied error, since premise.user_id != current_user.id -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
REDACTED! Okay, it''s 100% my error. Ability#initialize IS getting called. The source of my woes: I was explicitly passing :user_id => 1001 to Premise#initialize, which was overriding the :user_id that CanCan was providing. It was bad luck (or bad judgement) that I chose 1001 as the id -- this caused it to work on the first test and fail on the second. The halos of Saint Bates and Saint Chelimsky are still untarnished! (Now I can go debug why respond_with @premise is getting a "Not Acceptable" response.) -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.