Mocking/Stubbing partials and helper methods in RSpec view specs
In my previous post I whined about not knowing how to mock/stub partials and helper methods in RSpec view specs. Now I have the answer and I’d like to thank the RSpec users mailing list and David Chelimsky for taking my phone call.
In short, it’s all about @controller.template
Stubs out the appropriately named a_helper_method and returns true. You can mock it out also like so:
Which is like the stub except that it checks to see that a_helper_method was called at least once
For partials you do this:
Which checks to make sure the partial _form.rhtml is rendered and that the view attempted to pass mock_cookie in as a local. Since I didn’t specify a return it will return nil and I don’t have to worry about what’s in the _form view (of course, I’ll spec it by itself). Cool.
There’s just one problem: You can’t mock/stub a partial inside a partial. Let’s say that inside _form is another partial and while I was specifying _form I wanted to mock it out like so:
But later in the spec when I do this:
I’m making a call to the template to render and it gets intercepted by the mocking framework! So not only do I get an error that the wrong thing was rendered (_form instead of _piece_of_form) but I’ve intercepted the call so I don’t get inside the view at all. Even if I were to expect the call to render _form I make inside the spec (which is weird) I wouldn’t be able to render the _form. Bummer.
Oh well, I got almost all of what I wanted.
In short, it’s all about @controller.template
@controller.template.stub!(:a_helper_method).and_return(true)
Stubs out the appropriately named a_helper_method and returns true. You can mock it out also like so:
@controller.template.should_receive(:a_helper_method).
at_least(:once).and_return(true)
Which is like the stub except that it checks to see that a_helper_method was called at least once
For partials you do this:
@controller.template.should_receive(:render).
with(:partial => 'form', :locals => {:cookie => mock_cookie})
Which checks to make sure the partial _form.rhtml is rendered and that the view attempted to pass mock_cookie in as a local. Since I didn’t specify a return it will return nil and I don’t have to worry about what’s in the _form view (of course, I’ll spec it by itself). Cool.
There’s just one problem: You can’t mock/stub a partial inside a partial. Let’s say that inside _form is another partial and while I was specifying _form I wanted to mock it out like so:
@controller.template.should_receive(:render).
with(:partial => 'piece_of_form')
But later in the spec when I do this:
render :partial => ‘form’
I’m making a call to the template to render and it gets intercepted by the mocking framework! So not only do I get an error that the wrong thing was rendered (_form instead of _piece_of_form) but I’ve intercepted the call so I don’t get inside the view at all. Even if I were to expect the call to render _form I make inside the spec (which is weird) I wouldn’t be able to render the _form. Bummer.
Oh well, I got almost all of what I wanted.
Comments