Hello, I found a solution that makes this test pass and it was simply to mock
out the controller's find method as such:

Herd.stub(:find).with(@persist_herd.id) { mock_herd }

I am probably not fully understanding RSpec but this feels strange to me.   
In my understanding of writing tests, you want to first prepare the test
environment by creating the proper database/objects relevant to the testing
environment, pass the relevant parameters and test the results of method you
are testing.    Mocking out this controller code @herd =
Herd.find(params[:herd_id]) with this
Herd.stub(:find).with(@persist_herd.id) { mock_herd } doesn't seem to let
the controller test it's own code?  Why can't the parameters I'm passing to
the controller be enough to test Herd.find(params[:herd_id]) ?

Please help me understand this?





clem_c_rock wrote:
> 
> Hello,
>   I'm completely new to Rspec testing and I'm finding it very difficult to
> mock specific objects.
> 
> In this test, I have a before block setup as such:
> 
> [code]
>   before do
>     setup_controller_for_warden
>     controller.session[:operation_id] = 1
>     @operator = Factory :operator
>     sign_in :operator, @operator
>             
>     @persist_herd = Herd.new
>     @persist_herd.operation_id = 1;
>     @persist_herd.herd_name = 'Persisted Herd
> (herd_rations_controller_spec)'
>     @persist_herd.save!
>   end
> 
>   describe "GET new" do
>     it "assigns a new herd_ration as @herd_ration" do
>       HerdRation.stub(:new){ mock_herd_ration }
>       Herd.stub(:find).with(1) { @persistant_herd }
>       
>       get :new, :herd_id => 1
>       assigns(:herd_ration).should be(mock_herd_ration)
>       response.should be_success
>     end
>   end
> 
> 
> and here's my controller method:
> 
>   def new
>     @herd_ration = HerdRation.new
>     @herd = Herd.find(params[:herd_id])
>     
>     if @herd
>       respond_with(@herd_rations, :layout=> !request.xhr?)
>     else
>       redirect_to(root_url, :notice => 'No herd selected for ration.')
>     end
>   end
> [/code]
> 
> Here's the catch - we have this groovy little plugin that globally
> enforces a model scope via a session id, in this case:
> session[:operation_id].
> 
> Here's the code for the plugin:
> 
> [code]
> module ApplicationScopeManager
> 
> 
>    mattr_accessor :global_scope
>    @@global_scope = []
> 
>    mattr_accessor :local_scope
>    @@local_scope = {}
> 
>    def self.included(base)
>       base.send :extend, ClassMethods
>    end
> 
>    def self.setup
>       yield self
>    end
> 
>    module ClassMethods
> 
> 
>       def method_missing(name, *args, &block)
> 
>          return acts_as_scope_manager($1, args) if name.to_s =~
> /^acts_as_scope_manager_for_(.*)/
>          
>          return honors_scope_of($1, args) if name.to_s =~
> /^honors_scope_of_(.*)/
>          
>          return current_scope_for($1) if name.to_s =~
> /^current_scope_for_(.*)/
>          
>          super
>       end
> 
>       def current_scope_for(scope)
>          Thread.current[scope.to_sym]
>       end
> 
>       def acts_as_scope_manager(scope, *args)
>          options = args[0].extract_options! if args
>          send :include, InstanceMethods
> 
>          set_global_scope(scope,options[:with_global_scope]) if
> options[:with_global_scope]
> 
>          send :before_filter, "set_scope_for_#{scope}".to_sym if
> self.ancestors.include? ActionController::Base
>          send :default_scope, where(scope.to_sym =>
> send("current_scope_for_#{scope}".to_sym)[:finder_scope]).create_with(scope.to_sym
> =>
>          send("current_scope_for_#{scope}".to_sym)[:creator_scope]) if
> (self.ancestors.include? ActiveRecord::Base) &&
> Thread.current[scope.to_sym]
>       end
> 
>       alias honors_scope_of acts_as_scope_manager
> 
>       private
> 
> 
>       def set_global_scope(scope, *args)
>          Thread.current[scope.to_sym] = {:global_scope => args}
>       end
> 
>    end
> 
>    module InstanceMethods
> 
>       def method_missing(name, *args, &block)
> 
>          return set_scope_for($1, args) if name.to_s =~
> /^set_scope_for_(.*)/
> 
>          super
>       end
> 
>       private
> 
>       def set_scope_for(scope, *args)
>          if session[scope].class == Array
>             application_scope = {:finder_scope => session[scope],
> :creator_scope => nil }
>          else
>             application_scope = {:finder_scope => [session[scope]],
> :creator_scope => session[scope] }
>          end
> 
>          application_scope[:finder_scope] =
> application_scope[:finder_scope] +
> Thread.current[scope.to_sym][:global_scope] if
> Thread.current[scope.to_sym][:global_scope]
> 
>          Thread.current[scope.to_sym] = application_scope
> 
>       end
> 
>    end
> end
> 
> [/code]
> 
> This plugin enforces any model that calls the honors_scope_of_operation_id
> to include a lookup of the session[:operation_id] in all database calls.  
> For instance if I do a Model.find(params[:id])  it will automatically add
> a WHERE "field_name"."operation_id" = to the where clause.    The problem
> I'm having is that I can't seem to mock the session[:operation_id] in my
> Rspec tests.    I thought setting it this way 
> controller.session[:operation_id] = 1 in the before block would have been
> sufficient.
> 
> Any ideas?
> 

-- 
View this message in context: 
http://old.nabble.com/Can%27t-get-this-Rspec-test-to-pass-tp32037786p32061805.html
Sent from the RubyOnRails Users mailing list archive at Nabble.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 [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en.

Reply via email to