[rspec-users] Verifying that a block calls a method

Scott Taylor mailing_lists at railsnewbie.com
Tue Apr 17 22:07:11 EDT 2007


On Apr 17, 2007, at 1:03 PM, nicholas a. evans wrote:

> On 4/17/07, Scott Taylor <mailing_lists at railsnewbie.com> wrote:
>> def my_fun
>>    my_fun2 do
>>         raise Error
>>    end
>> end
>>
>> I know that I can verify that the method receives my_fun2.  How can I
>> mock/stub out the example to verify that it calls raise Error?
>
> Have you tried "should raise_error(...)"?
>
> lambda { my_fun }.should raise_error

Sure, I have - the problem is that the method my_fun2 only raises  
error under certain conditions - if for instance, Control-C is  
pressed.  It is quite different from a block like the following, in  
which the method call is guaranteed to execute:

def my_fun3
	[1,2,3].each { |x| puts x }
end

Then a spec like this should work just fine:

describe "my_fun3" do
   it "should call puts on the first element" do
     obj.should_receive(:puts).with(1)
     obj.my_fun3
   end
end

The example shows that the second method being called (puts), should  
be mocked (because you don't actually want to dump the numbers 1-3 to  
the terminal during your specs.

How do you mock out my_fun3?  The only clear advise I've gotten is to  
pass my_fun3 a stream, and let the default parameter be a STDOUT  
stream, like so:

def my_fun3(stream = STDOUT)
   [1,2,3].each { |x| stream.puts x }
end


describe "my_fun3" do
   setup do
     @io = mock(io)
     @io.stub!(:puts).and_return @io
   end

   it "should call puts on the first element" do
     @io.should_receive(:puts).with(1)
     obj.my_fun3
   end
end


Every time you use this method in production, you just leave off the  
parameter, and it defaults to calling puts (as normal).  The stream  
parameter is only used during testing.  This is a little disturbing,  
because now you have to change the source to fit your tests for code  
that will never be used in production.  Luckily it's not a big  
change, so it's probably not a big deal.

The specific example that I'm dealing with raises an error *only*  
when pressing ^C.

def add_sigint_handler
   trap("INT") { raise Interrupt }
end

Raise only gets called if ^C (or an INT signal) is received.  So how  
would I spec that method?

The one thought that I had was that I should be able to pass the  
block to the method as the last parameter.  Unfortunately, this  
doesn't seem to work.

Any other thoughts?

Thanks,

Scott Taylor






>
> http://rspec.rubyforge.org/rdoc/classes/Spec/Matchers.html#M000290
>
> -- 
> Nick
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users



More information about the rspec-users mailing list