dynamic rspec setup methods

Courtenay : April 16th, 2007

Got too much rspec setup code, or just want to DRY it out? Here's how I do it. Maybe there's a better way? (Fortunately, you can define as many setup methods as you like, and rspec will run them all. The trick is in getting a module to define the setup method for you)

module SetupCart
  def self.included(base)
    return unless base.class.name == 'Spec::Runner::ContextEvalModule'
    base.setup do 

      @cart = mock_model Cart, :to_param => '1aaBAX-34256'
      controller.stub!(:find_cart)
      controller.stub!(:set_person_var)
      assigns[:cart] = @cart

    end # setup
  end # included
end # module

and the spec

context "The cart controller" do
  include SetupCart
  setup do 
    @cart_items = mock "Association proxy"
    ...
  end

  ...
end

Now for the explanation: rspec will include the module twice, and the second time it does so "base" is Class. I didn't delve into the source to determine why.

1 Response to “dynamic rspec setup methods”

  1. Chris McGrath Says:

    For test/spec, I do the following:

    default_setup = Proc.new do
      @foo = Bar.new
    
      # if there are some helpers you want in a specific spec file
      # for creating test users etc.
      # put them in a module somewhere
      self.class.send(:include, FooTestHelper)
    end
    
    ... outside the contexts ...
    
    module FooTestHelper
      def something(some_arg)
       ...
      end
    end
    

    Then in the code:

    context "foo" do
      setup &default_setup
    
      ...
    end
    

    And if you need the setup in a context to do something else as well

    context "bar" do
      setup do
        instance_eval &default_setup
        @baz = Foo.new(:baz)
      end
    
      ....
    end
    

    Not sure if this will work with rspec, but I don’t see why it shouldn’t. (Then I know nothing about rspec internals :) )

Sorry, comments are closed for this article.