rspec-rails + rabl rendering views even if I don't want them to be rendered?#565

Labels

Milestone

Assignee

3 participants

This is verbatim of my stackoverflow question, but I did some debugging and think that it's not an issue with my setup.

I'm using rabl 0.6.13, rspec-rails 2.10.1, and rails 3.2.6.

I'm trying to spec my controllers in isolation, but for some reason my rabl templates are throwing me all sorts of undefined method exceptions on the mocks I use in my controller specs. I am not using render_views. I thought rspec did not process views unless you specify render_views in the controller spec. I've run debugger to ensure that render_views? evaluates to false in the before block rspec-rails inserts. Has anyone else run into this problem?

Basically I put a debugger in Haml::Plugin.call and saw that it was only breaking on that statement if my rspec context included render_views (using the param format => :html). Then I noticed that if I put that same debugger statement ActionView::Template::Handlers::Rabl.call the spec would break there regardless of whether or not I included render_views in the rspec context (using the param format => :json). Does that make sense? At first I thought it was rabl... but now it seems like something is going on in rails or rspec-rails that is causing rendering when the format is json or when the handler is rabl or some combination of both. Is that intended behavior?

On Wed, Jun 20, 2012 at 1:13 PM, Aaron Gibralter <reply@reply.github.com> wrote:
This is verbatim of my stackoverflow [question](http://stackoverflow.com/q/11125157/59639), but I did some debugging and think that it's not an issue with my setup.
I'm using rabl 0.6.13, rspec-rails 2.10.1, and rails 3.2.6.
I'm trying to spec my controllers in isolation, but for some reason my rabl templates are throwing me all sorts of undefined method exceptions on the mocks I use in my controller specs. I am not using render_views. I thought rspec did not process views unless you specify render_views in the controller spec. I've run debugger to ensure that render_views? evaluates to false in the before block rspec-rails inserts. Has anyone else run into this problem?
Basically I put a `debugger` in `Haml::Plugin.call` and saw that it was only breaking on that statement if my rspec context included `render_views` (using the param `format => :html`). Then I noticed that if I put that same debugger statement `ActionView::Template::Handlers::Rabl.call` the spec would break there regardless of whether or not I included `render_views` in the rspec context (using the param `format => :json`). Does that make sense? At first I thought it was rabl... but now it seems like something is going on in rails or rspec-rails that is causing rendering when the format is json or when the handler is rabl or some combination of both. Is that intended behavior?

It's not that rspec does or doesn't render_views (misleading name, but
legacy from older versions that actually didn't render them) - it
stubs them with blank template. It's possible that the way it does so
is bypassed or overridden by rabl (with which I have zero experience).
Take a look at https://github.com/rspec/rspec-rails/blob/master/lib/rspec/rails/view_rendering.rb
to get an idea about how this works and maybe it will help you in your
debugging effort.
HTH,
David

But in the end, after the compile! is done, view.send(method_name, locals, buffer, &block) evaluates to "" for when html is the format and haml is the handler, and view.send(method_name, locals, buffer, &block) raises an exception of undefined method error because a mock gets touched in my rabl template.

And strangely, when I step into the view.send method (again, with render_viewsfalse) I find myself in either index.json.rabl or index.html.haml.

I'm still wondering though if it's possible to cut of template rendering at a higher level than is currently implemented in rspec-rails. Even with the stubbing of blank templates, a lot of the underlying template handler (haml, rabl, etc.) gets called without render_views on.

Basically rspec-rails creates a new ActionView::Template passing "" as the source for the initializer. Here's the thing though, the initializer sets @source = "" in ActionView::Template#initialize, but the compile method pretty much ignores @source:

I believe you're right on the file read. That shouldn't be there. It came from this commit but included no explanation besides a reference to an issue that the author of the patch had. It looks like a hack. I'll push to master a simple source = template.source and you can try it from there.

Thank you, @databyte! I think that solves it for now. And sorry for the trouble, @dchelimsky. I would, however, like to hear your thoughts on stubbing out the call method -- it could be overkill though...

Yeah it seems that rspec-rails works in the vast majority of cases (this rabl issue was the only one I've run into). But if the result of the call is going to be basically nothing anyway (just skeleton compiled haml code and rabl code), why not just stub out that call code and maybe speed up controller specs that are running in isolation? Eh, maybe there are some template languages where the call code has significant side effects for the controller... in which case stubbing that out would break specs.