I was going through an older project of ours and cleaning up some specs and noticed how often we were doing the same thing in several places. When we started the project, we didnât get the benefits of shared groups. Now that we have some time to go through and update some of our older specs, Iâve been trying to take advantage of the features currently available in RSpec. One feature that I havenât seen a lot of mention of by people is shared groups, so I thought Iâd take a few minutes to write up a quick intro to using it.
To pick some low-hanging fruit, letâs take an all-too-familiar method,
which you might be familiar with⌠login_required
. Sound familiar?
Have you found yourself stubbing login_required
over and over
throughout your specs?
describe Admin::DohickiesController, âindexâ do
before( :each ) do
controller.stub!( :login_required )
Dohicky.should_receive( :paginate ).and_return( Array.new )
get :index
end
âŚ
end\
If youâre requiring that a user should be logged in when interacting
with most of the application (as in the case of an administration
section/namespace), you might want to consolidate some of your work into
one shared specification group. The basic premise behind this is that
you can write a typical describe
block and load it into any other spec
groups that you need. For example, in our case, weâll need to stub
login_required
in several places. We can set this up in one shared
group and reference it wherever necessary.
For example, here is what weâll start off with.
describe âan admin user is signed inâ do
before( :each ) do
controller.stub!( :login_required )
end
end
describe Admin::DohickiesController, âindexâ do
âŚ\
However, the new describe block isnât accessible from the block at the
bottom of the example⌠yet. To do this, we just need to pass the
option: :shared => true
as youâll see in the following example.
describe âan admin user is signed inâ, :shared => true do
ruby\
`before( :each ) do
ruby\
controller.stub!( :login_required )ruby\
`end
ruby
end
``ruby\
Great, now we can reference it by referring to it with:
it_should_behave_like SharedGroupName
. In our example above, this
would look like:
describe âan admin user is signed inâ do
before( :each ) do
controller.stub!( :login_required )
end
end
describe Admin::DohickiesController, âindexâ do
it_should_behave_like âan admin user is signed inâ
before( :each ) do
Dohicky.should_receive( :paginate ).and_return( Array.new )
get :index
end
âŚ
end
describe Admin::DohickiesController, ânewâ do
it_should_behave_like âan admin user is signed inâ
before( :each ) do
dohicky = mock_model( Dohicky ) Dohicky.should_receive( :new ).and_return(
dohicky
)
get :new
end
âŚ\
Thatâs it! Pretty simple, eh? We can now reference this shared group in
any describe blocks that we want to. A benefit to this approach is that
we can make change the authentication system (say, we decide to switch
it entirely and/or even just change method names, set any other
prerequisites necessary when an admin is signed in), weâll have a single
place to change in our specs. (tip: you can put these in your
spec_helper
file)
You can learn more about it_should_behave_like
and other helpful
features on the RSpec documentation
site.
If you have any suggestions on better ways of handling things like this, please follow up and share your solutions. Iâm always looking to sharpen my tools. :-)
Update
In response, Bryan Helmkamp suggests that a
better solution is to define a method in our specs like, for example:
build_mock_user_and_login
. then calling it in our before(:each)
. So,
maybe the approach above isnât the most ideal method but I did wantt o
draw some attention to it_should_behave_like
. I suppose that I need a
better example.. another post, perhaps? :-)
Also, Ed Spencer has posted an article titled, DRYing up your CRUD
controller
RSpecs,
which will introduce you mor to it_should_behave_like
.
Thanks for feedback people!
Related Posts
- [Be Careful that you donât Stub your Big
Toe](http://www.robbyonrails.com/articles/2007/02/13/be-careful-that-you-dont-stub-your-big-toe)
```text
- [Spec Your
```text
Views](http://www.robbyonrails.com/articles/2007/08/02/spec-your-views)