10

Given a parent class Fruit and its subclasses Apple and Banana, is it possible to stub the method foo defined in Fruit, so that any calls to method foo on any instances of Apple and Banana are stubbed?

class Fruit
  def foo
    puts "some magic in Fruit"
  end
end
class Banana < Fruit
  ...
end
class Apple < Fruit
 ...
end

Fruit.any_instance.stubs(:foo) did not work and it looks like it only stubs for instances of Fruit. Is there a simple way to achieve this other than calling stubs for every subclasses?

Found this link raising the similar question but it looks like it has not been answered yet. http://groups.google.com/group/mocha-developer/browse_thread/thread/99981af7c86dad5e

Vega
  • 27,856
  • 27
  • 95
  • 103
Innerpeacer
  • 1,321
  • 12
  • 20

3 Answers3

10

This probably isn't the cleanest solution but it works:

Fruit.subclasses.each{|c| c.any_instance.stubs(:foo)}
weexpectedTHIS
  • 3,358
  • 1
  • 25
  • 30
  • Yes, it works for this simple example. But it would be a bit clumsy if there are many sub classes. Also it does not work on ActiveRecord models, because the method is [overridden in base.rb](http://stackoverflow.com/questions/1195531/listing-subclasses-doesnt-work-in-ruby-script-console). I was actually looking for a way to stub a method for all controllers and models. – Innerpeacer Sep 26 '11 at 05:38
  • This method worked well for me, except using `c.constantize.any_instance.stubs(:foo)` – jackbot Mar 05 '13 at 17:31
1

UPDATE of @weexpectedTHIS answer for Rspec 3.6:

 Fruit.subclasses.each do |klass|
    allow_any_instance_of(klass).to receive(:foo).and_return(<return_value>)
 end
Francois
  • 1,367
  • 1
  • 15
  • 23
0

If your subclasses have subclasses, you may have to traverse them all recursively. I did something like this:

def stub_subclasses(clazz)
  clazz.any_instance.stubs(:foo).returns(false)
  clazz.subclasses.each do |c|
    stub_subclasses(c)
  end
end
stub_subclasses(Fruit)
Jesse Shieh
  • 4,660
  • 5
  • 34
  • 49