Can I override a method in RSpec for just one argument call

I have a mechanism to include features across multiple projects (one using RSpec 1 with Rails 2 and one with RSpec 2 / Rails 3), and I'm looking for a better way to override just one feature, without doing anything with other features. Ultimately, I'm looking for a way to stub a method when it calls a particular argument, and behave normally otherwise.

Close

Project::Config.should_receive(:feature_enabled?).with('new_feature').any_number_of_times.and_return(true)
get :index # calls feature_enabled? for a few other features too

>> <Project::Config (class)> expected feature_enabled? with 'new_feature' but received it with 'some old feature'

      

Works, but I'm looking for something a little cleaner, especially in cases where there may be multiple up {} blocks at different levels to allow different functionality.

Project::Config.should_receive(:feature_enabled?).with('new_feature').any_number_of_times.and_return(true)
# expect any other calls
Project::Config.should_receive(:feature_enabled?).any_number_of_times
# I can't override any features here.  This is annoying if I try to set up expectations at a few different levels
get :index # might call feature_enabled? for a few features

      

This also fails:

Project::Config.stub(:feature_enabled?).with('new_feature').and_return(true)
get :index

>> undefined method `feature_enabled?' for Project::Config:Class

      

Ideally, I could do something on one line that doesn't affect other declaration_functions? calls. If there is anything that just works for RSpec2, that's great, as we'll update another project at some point.

+3


source to share


2 answers


The best solution I have found for calling the original method works like this:



method = Project::Config.method(:feature_enabled?)

Project::Config.stub(:feature_enabled?).and_return do |arg|
  method.call(arg)
end

Project::Config.should_receive(:feature_enabled?).with('new_feature').and_return(true)

      

+3


source


Here's a possibly slightly cleaner alternative available in RSpec 3:

allow(Project::Config).to receive(:feature_enabled?).and_wrap_original do |method, arg|
  case arg
  when 'new_feature'
    true
  else
    method.call(arg)
  end
end

      



If you know you only need one case, then you can also use ternary or even simple ||

:

allow(Project::Config).to receive(:feature_enabled?).and_wrap_original do |method, arg|
  arg == 'new_feature' || method.call(arg)
end

      

0


source







All Articles