RSpec mocking a nested model in Rails - ActionController problem
- by emson
Hi All
I am having a problem in RSpec when my mock object is asked for a URL by the ActionController. The URL is a Mock one and not a correct resource URL.
I am running RSpec 1.3.0 and Rails 2.3.5
Basically I have two models. Where a subject has many notes.
class Subject < ActiveRecord::Base
validates_presence_of :title
has_many :notes
end
class Note < ActiveRecord::Base
validates_presence_of :title
belongs_to :subject
end
My routes.rb file nests these two resources as such:
ActionController::Routing::Routes.draw do |map|
map.resources :subjects, :has_many => :notes
end
The NotesController.rb file looks like this:
class NotesController < ApplicationController
# POST /notes
# POST /notes.xml
def create
@subject = Subject.find(params[:subject_id])
@note = @subject.notes.create!(params[:note])
respond_to do |format|
format.html { redirect_to(@subject) }
end
end
end
Finally this is my RSpec spec which should simply post my mocked objects to the NotesController and be executed... which it does:
it "should create note and redirect to subject without javascript" do
# usual rails controller test setup here
subject = mock(Subject)
Subject.stub(:find).and_return(subject)
notes_proxy = mock('association proxy', { "create!" => Note.new })
subject.stub(:notes).and_return(notes_proxy)
post :create, :subject_id => subject, :note => { :title => 'note title', :body => 'note body' }
end
The problem is that when the RSpec post method is called.
The NotesController correctly handles the Mock Subject object, and create! the new Note object. However when the NoteController#Create method tries to redirect_to I get the following error:
NoMethodError in 'NotesController should create note and redirect to subject without javascript'
undefined method `spec_mocks_mock_url' for #<NotesController:0x1034495b8>
Now this is caused by a bit of Rails trickery that passes an ActiveRecord object (@subject, in our case, which isn't ActiveRecord but a Mock object), eventually to url_for who passes all the options to the Rails' Routing, which then determines the URL.
My question is how can I mock Subject so that the correct options are passed so that I my test passes.
I've tried passing in :controller = 'subjects' options but no joy.
Is there some other way of doing this?
Thanks...