views:

371

answers:

2

I have a Rails model named Xpmodule with a corresponding controller XpmoduleController.

class XpmoduleController < ApplicationController
  def index
    @xpmodule = Xpmodule.find(params[:module_id])
  end

  def subscribe
    flash[:notice] = "You are now subscribed to #{params[:subscription][:title]}"
    redirect_to :action => :index
  end
end

The original intent was to name the model Module which for obvious reasons doesn't work. However I still want to have the URLs look like /module/4711/ therefore I added this to my routes.rb:

map.connect '/module/:module_id', :controller => 'xpmodule', :action => 'index'

map.connect '/module/:module_id/subscribe', :controller => 'xpmodule',
  :action => 'subscribe'

Now I want to test this controller with Rspec:

describe XpmoduleController do
  fixtures :xpmodules
  context "index" do
    it "should assign the current xpmodule" do
      xpm = mock_model(Xpmodule)
      Xpmodule.should_receive(:find).and_return(xpm)
      get "index"
      assigns[:xpmodule].should be_an_instance_of(Xpmodule)
    end
  end
end

for which I get No route matches {:action=>"index", :controller=>"xpmodule"}. Which of course is sort-of right, but I don't want to add this route just for testing purposes. Is there a way to tell Rspec to call a different URL in get?

A: 

Head, meet wall, Wall, meet head. bang.

Not getting an answer on SO is a sure sign that I should try harder. Therefore I added the /xpmodule route explicitly to the routes.rb. Just to notice that the tests are still failing. To cut a long story short:

it "should assign the current xpmodule" do
  xpm = mock_model(Xpmodule)
  Xpmodule.should_receive(:find).and_return(xpm)
  get "index", :module_id => 1
  assigns[:xpmodule].should be_an_instance_of(Xpmodule)
end

is the solution.

jhwist
+1  A: 

As far as I can tell you're testing controller action and not routing to that action. These are two different things!

Try this for starters:

it "should map xpmodules controller to /modules url" do
  route_for(:controller => "xpmodule", :action => "index").should == "/modules"
end

Apply for other actions as well. If you want to do a reverse routing (from url to controller/action) then do this:

it "should route /modules url to xpmodules controller and index action" do
  params_from(:get, "/modules").should == {:controller => "xpmodules", :action => "index"}
end
Eimantas
See my answer, I just wasn't calling the action with the right parameters.
jhwist