Ruby Forum RSpec > Re: spec'ing calls to super (or other Ruby keywords)

Posted by Al Chou (Guest)
on 03.05.2008 17:26
(Received via mailing list)
In the particular case of super, another approach, though perhaps not 
using the spec framework, would be to assert (a la Test::Unit) that your 
class is a subclass of the intended superclass.  To be truly anal, also 
assert that the superclass has a method with the same name as the 
subclass's method of interest and that the subclass has that method, 
too.  But all this seems deeply into the xUnit world, and far from the 
BDD way.

Al

----- Original Message ----
From: John D. Hume <duelin.markers@gmail.com>
To: rspec-users <rspec-users@rubyforge.org>
Sent: Saturday, May 3, 2008 7:49:11 AM
Subject: Re: [rspec-users] spec'ing calls to super (or other Ruby 
keywords)

I believe calls to super are sufficiently internal to the Ruby 
interpreter that a mocking framework can't intercept them without doing 
separate implementations for separate Ruby interpreters (and likely even 
separate versions).  I could be wrong, but even so I'd recommend a 
different approach.

If your need is really as simple as your example, what you have is just 
a method that has to get two things done: the base save and one 
additional call.  You can write one (or more) example for each of those 
two things without your spec knowing that one of those things gets done 
by calling super.  (You might object that by spec'ing the base #save 
behavior you're spec'ing the framework.  I'd say you're USING the 
framework to spec something your code does.  To be clear, I'm not 
suggesting you spec every detail of what save does: just something to 
make sure the record actually lands in the db.)

(Sidebar: Keep in mind the return value if you're really overriding 
#save like that.)

If you're dead set on spec'ing that the super method gets called, there 
are a couple of hideous ways of doing it that will leak out of your 
example.  Namely, you can (in your spec) redefine the method in the 
superclass and verify it gets called or (also in your spec, and this 
one's a little less leaky) have the class under test include a module 
that defines the same method and verify it gets called.  Don't do either 
of those though (unless it's just to prove to yourself that they're 
possible).

-hume.


On Fri, May 2, 2008 at 5:17 PM, Matt McNeil <nabble.108@xoxy.net> wrote:

Hi there,

How does one spec an invocation of a Ruby keyword, such as super in this
case?

class User < ActiveResource::Base
  # faking the ActiveRecord before/after_save observers
  def save
    super
    UserMailer.deliver_activation(self) if recently_activated?
  end
end

Does the solution look anything like the following?

describe User do
  describe '#save' do
    it "should call save on the parent class" do
      # something.should_receive(:something)
      @user.save
    end
  end
end

Any thoughts?

Thanks much,
Matt






      ____________________________________________________________________________________
Be a better friend, newshound, and
know-it-all with Yahoo! Mobile.  Try it now. 
http://mobile.yahoo.com/;_ylt=Ahu06i62sR8HDtDypao8Wcj9tAcJ
Posted by Scott Taylor (Guest)
on 03.05.2008 22:55
(Received via mailing list)
On May 3, 2008, at 11:09 AM, Al Chou wrote:

> In the particular case of super, another approach, though perhaps  
> not using the spec framework, would be to assert (a la Test::Unit)  
> that your class is a subclass of the intended superclass.  To be  
> truly anal, also assert that the superclass has a method with the  
> same name as the subclass's method of interest and that the subclass  
> has that method, too.  But all this seems deeply into the xUnit  
> world, and far from the BDD way.
>
> Al

The truth is that you shouldn't be spec'ing calls to the super
"method", but rather the behaviour of super.  One quick way to do this
is as so:

[BaseClass, Subclass].each { |klass|
  it "should do whatever super does" do
    klass.new.foo_bar.should == :baz
  end
end

Your original example is a little trickier, because you didn't write
the base class, and you probably aren't going to spec it out.  There's
obviously great complexity in that call to super.  Now you know why
none of us like writing specs against rails apps.

Scott