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@googlegroups.com.
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.

Search Discussions

  • Fearless Fool at Apr 5, 2012 at 11:03 pm
    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@googlegroups.com.
    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.
  • Fearless Fool at Apr 6, 2012 at 12:10 am
    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@googlegroups.com.
    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 at Apr 6, 2012 at 7:45 am

    On 6 April 2012 01:10, Fearless Fool 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@googlegroups.com.
    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.
  • Fearless Fool at Apr 6, 2012 at 3:44 pm

    Colin Law wrote in post #1055228:
    On 6 April 2012 01:10, Fearless Fool 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.

    Colin
    Colin, 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@googlegroups.com.
    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.
  • Fearless Fool at Apr 6, 2012 at 4:03 pm
    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@googlegroups.com.
    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.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouprubyonrails-talk @
categoriesrubyonrails
postedApr 5, '12 at 9:54p
activeApr 6, '12 at 4:03p
posts6
users2
websiterubyonrails.org
irc#RubyOnRails

2 users in discussion

Fearless Fool: 5 posts Colin Law: 1 post

People

Translate

site design / logo © 2022 Grokbase