Using the RSpec Around Hooks

A couple of weeks back, I was working on some RSpec tests that required a different setup and tear-down than other tests in the app. We had “database cleaner”: providing cleanup for us to prevent test interaction, but certain tests we created needed a heavier cleanup than others. We had a simple before(:each) and after(:each) with the setup and tear-down, but that had to change to accommodate certain types of tests.

The Setup

We have defined RSpec metadata on certain tests that need extra attention in the setup or tear-down stages like so:

Could not embed GitHub Gist 5156864: Not Found

This allows us to filter (“RSpec filtering in before/after hooks”: the tests with type :spec_type in our spec_helper.rb file. The :spec_type is arbitrary in this case, it could be anything (:unit, :special_test, :things_need_more_cleaning, etc). In our spec_helper.rb we can now target these tests for extra work with befores and afters:

Could not embed GitHub Gist 5156864: Not Found

Looking back at our project, we had a few of these guys set up to provide database cleanup between tests, but they didn’t care about the test type — we had only one need fore cleanup. After introducing a couple of new test types, we had need for different cleanup methods, so we would have written this:

Could not embed GitHub Gist 5156864: Not Found

This example shows a general setup for any test type, but for some cases of test types it had some special hooks. In this case, the :special_type and :fancy_type shared the same setup and tear-down — not very DRY, huh? After a little looking, we found the RSpec around hook.

RSpec Around Hook Explained

The “around hook”: allows us to DRY up the setup and tear-down of our tests. DRYing up the tests is not the only thing around() lets us do; it also allows us to wrap our before and afters with another layer of setup/teardown. This is how we came out:

Could not embed GitHub Gist 5156864: Not Found

Our sample would run in this order:

# around each setup (general or special setup — dependent on the if statement)
# before each
# the actual spec
# after each
# around each tear-down (general or special tear-down — dependent on the if statement)

There are plenty of possibilities with the around, before, and after hooks, especially since they can be targeted to all tests, a suite of tests, and each test.

  • Josh says:

    Thanks, but your forgot to pass the |example| variable to your around block. ;)

    • Jared Sartin Jared Sartin says:

      Ah, thanks! Sorry if that caused any confusion!

  • Comments are closed.