Gavin Morrice

is a web and iOS developer from Edinburgh, Scotland.

more about me ยป

How to test routes in a Rails 3.1 mountable engine

This problem has been eluding me for a few weeks...

While working on Blogit I wanted to write specs for the routes but kept hitting ActionController::RoutingError with every approach I tried.

Finally I discovered this solution:

# spec/routing/post_routing_spec.rb

...

before do
  @routes = Blogit::Engine.routes
end

it "routes /posts/page/:page to posts#index with page param" do
  { get: "posts/page/2" }.should route_to({
    controller: "blogit/posts",
    action: "index",
    page: "2"
  }
end

Setting the @routes variable to the Blogit Engine's routes seemed to do the trick nicely!

There's something really dirty and "hacky" about this approach though - there surely is a better way? If anyone knows, please leave a comment below.


How to write a controller spec for a Rails 3.1 Engine

This week I've been building a Rails gem which mounts as an engine.

When I started to spec out the controllers I kept hitting ActionController::RoutingErrors telling me that no route matches the controller and action I was testing.

I knew this had to be a problem within my specs or with Rspec itself because routes worked fine in the browser.

On poking around the Rails ActionDispatch::Routing code I discovered the :use_route option.

Applying this to the controller specs was the fix I was looking for!

Here's a quick demo:

# in my_gem/spec/controllers/my_gem/my_controller.rb
require "spec_helper"

# Where MyGem is the namespace I've isolated my Gem under
describe MyGem::MyController do

  describe "GET /index" do

    # get the index action
    def do_get
      # :my_gem should be the name of your engine
      get :index, :use_route => :my_gem
    end
    it "should not raise an error when I try a simple GET request!" do
      lambda { do_get }.should_not raise_exception
    end

  end

end

If you have any interesting Rails 3.1 engines that you're working on, leave a comment with a link below :)