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.
source to share
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)
source to share
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
source to share