109

I am stuck with a problem when testing my controllers with RSpec - the response.body call always returns an empty string. In browser everything renders correctly, and cucumber feature tests seem to get it right, but RSpec fails each and every time.

Other expectations on the response object, such as response.should render_template('index') pass without any problems.

Have any of you encountered this problem before? Perhaps the response html can be obtained in some other way?

As for versions, Rails 2.1.0, RSpec 1.2.7.

Toms Mikoss
  • 9,097
  • 10
  • 29
  • 41

4 Answers4

206

By default, rspec-rails hacks into Rails to prevent it from actually rendering view templates. You should only test the behavior of your actions & filters your controller tests, not the outcome of template rendering — that's what view specs are for.

However, if you wish to make your controller specs render templates as the app normally would, use the render_views directive:

describe YourController do
  render_views
  ...
end
epidemian
  • 18,817
  • 3
  • 62
  • 71
mislav
  • 14,919
  • 8
  • 47
  • 63
  • 2
    I've been working with Rails for years and now I finally understand the difference between controller and request specs. Thanks! – Brian Underwood Feb 18 '16 at 10:11
  • thanks, the render_views works fine when I test rails API, it rendered the json template and put the result in the response.body, if not use render_views, response.body == "" – dayudodo Dec 02 '20 at 12:08
  • I am conscientiously choosing to render view templates in my controller tests. I do this to replace the extremely slow end to end tests, with nokogiri to validate the results of my controller actions. I hate hearing the word should. – Taylored Web Sites Mar 14 '23 at 15:40
6

RSpec 2+: If you want to check end to end - url to response body - use a request spec instead of a controller spec.

Thomas
  • 3,004
  • 23
  • 17
2

As I worked with a similar problem (that led me to this question), it occurred to me that there are different ways to skin the same cat. In other words, rather than checking for the body text, you might be able to check the content of the flash.

response.body.should =~ /Invalid email or password/

might be an equivalent check to:

flash[:alert].should == "Invalid email or password"

To me the latter seems a bit more flexible as it will run either way, but it may not be appropriate in all cases.

Cheers,

John

John Lockwood
  • 3,787
  • 29
  • 27
2

By default, RSpec-rails configuration disables rendering of templates for controller specs

One of the ways to fix this is by making sure to enable the render_views setting in your rails_helper.rb file. In this way, you make it able to work globally in all your tests.

RSpec.configure do |config|
  config.render_views
end

Or use render_views declaration an individual group:

describe User do
  render_views
end

You can read more about this here.

Nesha Zoric
  • 6,218
  • 42
  • 34