Search code examples
rspecrspec2

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


I've got a feature enablement mechanism in a couple of 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 having to do anything with other features. Ultimately I'm looking for a way to stub a method when it's called with 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, particularly in cases where there might be a few before{} blocks at different levels enabling different features.

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'd be able to do something in one line that doesn't affect other feature_enabled? calls. If there's something that just works for RSpec2 that's fine, since we'll update the other project at some point.


Solution

  • The best solution I've found to calling through to the original method works thusly:

    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)