Rails 3 how to reset controller before_filters between specs?

996 views Asked by At

I'm writing specs for a plugin which has different modules that the user can choose to load. Some of these modules dynamically add before_filters to ApplicationController.

The problem is sometimes if the spec for module X runs and adds a before_filter, the spec for module Y which runs later will fail. I need somehow to run the second spec on a clean ApplicationController.

Is there a way to remove before filters or reload ApplicationController completely between specs?

For example in the following specs, the second 'it' does not pass:

describe ApplicationController do
  context "with bf" do
    before(:all) do
      ApplicationController.class_eval do
        before_filter :bf

        def bf
          @text = "hi"
        end

        def index
          @text ||= ""
          @text += " world!"
          render :text => @text
        end
      end
    end

    it "should do" do
      get :index
      response.body.should == "hi world!"
    end
  end

  context "without bf" do
    it "should do" do
      get :index
      response.body.should == " world!"
    end
  end
end
2

There are 2 answers

1
Jimmy On

You should be able to do this using context blocks to separate the two sets of examples.

describe Something do
  context "with module X" do
    before(:each) do
      use_before_fitler
    end

    it_does_something
    it_does_something_else
  end

  context "without module X" do
    it_does_this
    it_does_that
  end
end

The before_filter should only affect the examples in the "with module X" context.

0
zetetic On

I'd use separate specs on subclasses rather than ApplicationController itself:

# spec_helper.rb
def setup_index_action
  ApplicationController.class_eval do
    def index
      @text ||= ""
      @text += " world!"
      render :text => @text
    end
  end
end

def setup_before_filter
  ApplicationController.class_eval do
    before_filter :bf

    def bf
      @text = "hi"
    end
  end
end

# spec/controllers/foo_controller_spec.rb
require 'spec_helper'

describe FooController do

  context "with bf" do
    before(:all) do
      setup_index_action
      setup_before_filter
    end

    it "should do" do
      get :index
      response.body.should == "hi world!"
    end
  end
end


# spec/controllers/bar_controller_spec.rb
require 'spec_helper'

describe BarController do
  before(:all) do
    setup_index_action
  end

  context "without bf" do
    it "should do" do
      get :index
      response.body.should == " world!"
    end
  end
end