[rspec-users] Help to spec a rails helper method that uses content_for

John D. Hume duelin.markers at gmail.com
Sun Jan 27 12:05:19 EST 2008

You're trying to test more than one thing in one spec.  The gutter
that's steered you into here is that you're looking for side-effects
of a method you've mocked.  Your spec says to make sure the template
calls "body_class" and to have the call return a string, but that's
not how the body_class method works: the real method passes that
string along to "content_for," which is what causes it to end up in
the layout.

There are really three responsibilities to specify: (1) the template
is supposed to provide the right body_class, (2) the body_class method
is supposed to format a string and pass it along to content_for, and
(3) the layout is supposed to put that content into the body tag.

For purposes of specifying the template's responsibility, I think
you've got all you need by saying

For the helper, you can just say in your helper spec
  self.should_receive(:content_for).with(:body_class, " class=\"funclass\"")
  body_class "funclass"
Note that I'm mocking the receiver of the method being tested, which
is a smell, but I think it's reasonable when dealing with app-specific
helpers that rely on Rails helper methods.  Also note that I'm
specifying that you change your implementation to pass the content as
the second argument to content_for.  That's a lot less ugly to mock
than the version with the block.

I don't have a good recommendation for specifying the layout's
responsibility for plopping the "body_class" content into the body
tag, but I think it ought to be pretty easy to do readably.  Maybe
someone with more view-spec experience could help out.


On Thu, Jan 24, 2008 at 11:00 AM, Ben Aldred <benaldred at gmail.com> wrote:
> Hi guys,
> I am a Rspec newbie and am having problems creating a spec for a RoR helper
> method.
> I have in fact already implemented the helper method and am trying to create
> retrospective specs. I know its the wrong way to do it but I am still
> learning Rspec.
> In my view I have a call to a helper method.
> <% body_class "users" %>
> which sets a CSS class declaration in the content_for block which is then
> used in the <body> tag in application.html.erb layout.
>   def body_class(class_name)
>     content_for(:body_class) { " class=\"#{class_name}\"" }
>   end
> I was trying the following in my view spec:
> template.should_receive (:body_class).with("users")
> .and_return(' class="users"')
> render "/admin/users/index.html.erb", :layout => "application"
> response.should have_tag(' body.users')
> I get a:
> Expected at least 1 element matching "body.users", found 0.
> <false> is not true.
> when I printed the response.body to screen it does not contain he CSS class
> declaration on the body tag, where as running mongrel and going to the page
> everything is fine.
> what am I doing wrong? I ended up doing:
> render "/admin/users/index.html.erb", :layout => "application"
> response[:body_class].should == ' class="users"'
> I am interested to know why my first attempt did not work.
> _______________________________________________
>  rspec-users mailing list
>  rspec-users at rubyforge.org
>  http://rubyforge.org/mailman/listinfo/rspec-users

More information about the rspec-users mailing list