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.