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-tp32037786p32037786.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 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.
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? -- 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.
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 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.