[rspec-users] Help with controller spec?

Matt Darby matt at matt-darby.com
Tue Jan 6 13:53:28 EST 2009

On Jan 6, 2009, at 1:16 PM, Stephen Eley wrote:

> On Tue, Jan 6, 2009 at 10:53 AM, Matt Darby <matt at matt-darby.com>  
> wrote:
>> I'm stumped. How would I go about specing the "update_sandbox"  
>> method?
> I couldn't hope to compete with David's answer when it comes to
> specifics, but more generally, it occurs to me that your question is a
> little imprecise and that could point to part of the cognitive
> disconnect.  You ask how to spec the method, but you're NOT specing
> the "update_sandbox" method in the example you posted.  You're specing
> a controller's "new" action.  Creating a stub or mock for a method
> isn't the same as specing it.  A spec tests something to see if it
> does what it's supposed to.  Mocking or stubbing is the opposite:
> instead of testing the method, you're pretending the method doesn't
> exist and replacing it with a cardboard cutout.

Hi Stephen!

My aim is to spec the Bid::new action; all it really does is call the  
#update_sandbox method with a particular block. If I am to test  
strictly the behavior of the action, I would really just be testing  
the View as it's based on RJS. The View is spec'd, but I need to  
simulate the actual updating of the View via the returned Javascript.

> Other things I noticed:
> 1.) There's really no point in putting identical stub!() and
> should_receive() declarations in the same example.  should_receive()
> does everything stub!() does and slightly more.  It replaces the
> method AND says "Complain if this doesn't get called."  When you see
> them used in the same spec file, what you're usually seeing is stub!()
> in the "before" blocks just to replace external interfaces and make
> sure nothing breaks, and then should_receive() in multiple individual
> examples to prove that things called when they should.

Good to know! That will really clean up my specs (and save me a ton of  

> 2.) On that note, it's becoming more and more the accepted practice to
> have only one "should" per example.  (Including "should_receives" or
> other mocks.)  That way, if one of the expectations breaks, you'll
> know which one from the "it should..." text and won't have to look at
> individual lines.

Agreed, however, I wasn't sure how to approach this case as I'm  
testing a method and a block at the same time. By the time I'd arrived  
at the spec I originally posted I was well into the "Grasping At  
Straws" phase.

> 3.) You _could_ probably make this spec work as it stands by changing
> the "update_sandbox" call to expect a Proc with the "render_to_string
> ..." block included; that's what actually happens when you call a
> method with a "do" block, you're passing it an anonymous Proc as a
> parameter.  Tweak it enough and I'll bet you could get this to work.

Duly noted.

> 4.) BUT, I agree with David, there's probably no point.  At this level
> your spec becomes sort of trivial; you're not even testing behavior
> any more, you're testing for the existence of certain lines of code.
> Think big picture: WHY are you testing?  What is it you want to prove?
> Your users don't care whether render_to_string() ever gets called
> with certain parameters, and tomorrow you won't care either.  You DO
> care whether the controller's "new" method responds with an
> appropriate block of Javascript when accessed via AJAX.  You can find
> that out by making the request and checking the response, but if you
> stub out the part that actually generates the Javascript, all you'll
> learn is "the controller get called and it responded."  If that's all
> you want to know, you could mock update_sandbox to return "neener
> neener" and test for THAT.  (And make sure to spec the
> update_sandbox() method thoroughly elsewhere.)

I don't necessarily care what #update_sandbox actually produces, I  
just want to make sure that it is called with the expected  
"render_to_string" call.

Can you clarify "making the request and checking the response"? Is it  
possible to just check the "xhr :get, :index" call for a standard hunk  
of Javascript? If so, problem solved -- again, I don't yet have a  
super firm grip on controller specing when AJAX/RJS is concerned. I'm  
eagerly awaiting David's book!

> 5.) OR...  You might gain some good food for thought by going to the
> MerbCamp videos (http://merbcamp.com/video) and watching Yehuda Katz's
> video on testing (http://merbcamp.com/video/katz1.mp4).  Don't worry
> about the Merb stuff; what he's describing is a general approach and
> it's just as applicable to Rails.  The philosophy is somewhat contrary
> to the "unit test everything in isolation" philosophy that many others
> espouse, but it doesn't hurt to learn both and decide which style
> suits you best.

I shall, thanks for the pointer.

> I personally found Yehuda's approach to be a slap of cold water and
> then a breath of fresh air; since I started it, I've almost entirely
> stopped mocking things, and I no longer have the frustrating feeling
> that I'm spending 10x longer on tests (and testing my tests, and
> debugging my tests) than I am on my application features.  But again:
> think for yourself, and decide what suits your goals and learning
> path.

Thank you for your reply, it was really very insightful and I'm sure  
others will learn from it as well!

> -- 
> Have Fun,
>   Steve Eley (sfeley at gmail.com)
>   ESCAPE POD - The Science Fiction Podcast Magazine
>   http://www.escapepod.org
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users

More information about the rspec-users mailing list