[rspec-users] [Rails] rails view helpers, BDD, and what to mock

Myron Marston myron.marston at gmail.com
Fri Sep 17 21:16:11 EDT 2010

On Sep 17, 12:48 pm, "Doug E." <d... at emeryit.com> wrote:
> Hi,
> I'm trying to understand BDD and proper testing technique. I'm testing
> a rails view helper method that checks user roles to see if a link
> should be shown. I'm using rails 2.3.8 and rspec version 1.3.0.  My
> helper looks like this:
> # welcome_helper.rb
> module WelcomeHelper
>  def manage_samples_link
>   return nil if current_user.blank?
>   if current_user.role?(:submitter) ||
>       current_user.role?(:reviewer) ||
>       current_user.role?(:admin)
>     link_to "Manage Samples", manage_samples_path
>   end
>  end
> end
> The spec code looks like this:
> # welcome_helper_spec.rb
> require 'spec_helper'
> describe WelcomeHelper do
>  %w{ submitter reviewer admin }.each do |rolename|
>   it "should return manage samples link for user with role
> #{rolename}" do
>     role = Role.new(:rolename => rolename)
>     user = User.new(:roles => [role])
>     helper.stub(:current_user).and_return(user)
>     link = %{<a href="/manage_samples">Manage Samples</a>}
>     helper.manage_samples_link.should == link
>   end
>  end
> end
> If the above doesn't format well, here's a gist:
>  https://gist.github.com/afd222a63193bf000ab8
> My question is, What should I be testing here?
> I stubbed current_user, but I haven't mocked the User object and its
> role? method. While I understand that this is the proper place to test
> the User#role? method, don't I want to know that this helper is
> returning the link only for those the admin, submitter, and reviewer
> users and not for, for instance, 'editors'?
> If I mock out user and stub it with something like:
>  user.stub!(:role?).and_return(true)
> Am I really testing anything other than the content of the link?
> It seems to me that there are two things to test:
> (1) that I get the right link; and
> (2) the logic; that is, that the correct users get the link
> And, it seems that if I don't use a User object, I don't really know
> whether the logic is correct or, secondarily, if some later change to
> the User#role? method has broken my helpers, views, etc.
> Is this correct? I apologize if this is too basic a question, but I'm
> trying to wrap my head around what rspec tests go where and how to
> structure them, and leave integration testing to cucumber.
> Thanks.
> Doug
> PS My apologies to the moderators if you've been getting spammed with
> different versions of this post as I've stumbled about trying to get
> my account set up.
> _______________________________________________
> rspec-users mailing list
> rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users

The presence of 3 clauses in your if statement suggests to me that you
have too much business logic in this helper.  I'd recommend you move
that into an appropriate method on your user model:

class User
  def can_manage_samples?
    [:submitter, :reviewer, :admin].any? { |r| role?(r) }

This should not be difficult to test in your user model spec.

Now your helper can be greatly simplified:

module WelcomeHelper
 def manage_samples_link
  link_to "Manage Samples", manage_samples_path if

This is far easier to test, and I believe that stubbing
#can_manage_samples? is an appropriate way to do so.  Your helper test
just needs to test 3 cases:

1.  No link should be rendered when current_user is nil.
2.  No link should be rendered when current_user.can_manage_samples?
returns false.
3.  The link should be rendered when current_user.can_manage_samples?
returns true.

Note that you may want to look into something like cancan[1] to help
with this (although, I've never used cancan myself).


[1] http://github.com/ryanb/cancan

More information about the rspec-users mailing list