Search code examples
rubyruby-on-rails-3rspecrubygemsrspec-rails

framework integration testing within a gem: how to set up rspec controller test for a gem rails integration


This question is NOT about how to test controllers in a rails app.

Developing a gem I want to test if my gem integrates in a rails controller. So running rspec in the gem root is outside the rails environment.

Now how do I write say a controller test which can use the rspec controller example group helpers like get or post?

IN particular if I set a metatag :type => :controller on an example group , how does rspec set up the rails environment and how can i hook into that in order to say set up routes, etc.

I'd rather not have to set up an entire rails app skeleton mostly empty. But I cannot even find info on how to do that. What is best practice to test a gem integrating to rails app or multiple frameworks.

These sources came closest to what I am after: Test (with RSpec) a controller outside of a Rails environment but this is for test unit. http://railsware.com/blog/2012/01/07/testing-gem-integration-with-multiple-ruby-frameworks/ but this is for capybara which directly hooks in a rails app class.

thanks all


Solution

  • Below is a nice minimal example of a rails controller integration test from a gem. my_gem. Assume that you are in a gem root with simple rspec setup (say with rspec --init). Then spec/rails_controller_integration_spec.rb will look like this.

    rspec/rails does the necessary requires, among them rspec/rails/example which sets up example group types based on metatags. The metatag :type => :controller drives the inclusion of the proper group module RSpec::Rails::ControllerExampleGroup which provides you with all the goodies of rails controller specing as well as all the goodies of ActionController::TestCase like get/post.

    Hope this helps.

    What I still don't get is how the Rails environment gets assigned. In particular what if I would like to set up two apps TestTailsApp1 and TestTailsApp2. any advice?

    require 'spec_helper'
    require 'my_gem'
    
    require 'rails'
    require 'action_controller/railtie' # allows ActionController::Base
    # crucial part here:
    require 'rspec/rails'
    # note that require 'rspec-rails' does not work
    
    module TestRailsApp
      class Application < Rails::Application
        # app config here
        # config.secret_token = '572c86f5ede338bd8aba8dae0fd3a326aabababc98d1e6ce34b9f5'
        # routes.draw do
        #   resources :models
        # end
      end
    
      class ApplicationController < ActionController::Base
        # setup
      end
    
    end
    
    describe 'My gem' do
    
      context "in a Rails controller", :type => :controller do
    
        controller(TestRailsApp::ApplicationController) do
          extend(RSpec::Rails::ControllerExampleGroup::BypassRescue)
          # example-specific setup for anonymous controller
          # https://www.relishapp.com/rspec/rspec-rails/docs/controller-specs/anonymous-controller
          def index
          end
        end
    
        before(:each) do
          # request needs to be setup to avoid path setting error
          @request = ActionController::TestRequest.new
        end
    
        describe "#index" do
          it "works" do
            get :index
            response.body.should == 'index content'
          end
        end
      end
    
    end