Rails 2: Your integration tests are lying

Integration tests call the whole rack middleware stack, but stubbornly return the last controller response, which can be completely different especially if you use warden or other middleware-tools.

See actionpack-2.3.14/lib/action_controller/integration.rb:342

To fix that and prepare for Rails 3 (which also relies on rack response) do this:

# test/test_helper.rb

if Rails::VERSION::MAJOR == 2
  # https://grosser.it/2012/10/19/rails-2-your-integration-tests-are-lying/
  # make integration tests use rack response, so we can test our middlewares
  # and not only the pure controller response

  ActionController::Base.class_eval do
    # this is usually done just-in-time by #process but we need to do it earlier
    include ActionController::Integration::ControllerCapture

    # then we hide last_instantiation from #process
    def self.last_instantiation;end
  end

  ActionController::Integration::Session.class_eval do
    def process_with_rackify(*args)
      process_without_rackify(*args)
    ensure
      # needed e.g. inside of assert_redirect_to
      capture = ActionController::Integration::ControllerCapture::ClassMethods

      # not set by original #process
      @response.redirected_to = @response.headers["Location"] if @response
      if @controller = capture.send(:class_variable_get, :@@last_instantiation)
        @request = @controller.request
        @response.template = @controller.response.template if @controller.response
        @controller.send(:set_test_assigns)
      end
    end
    alias_method_chain :process, :rackify
  end
end

One thought on “Rails 2: Your integration tests are lying

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s