RSpec mocking a nested model in Rails - ActionController problem

Posted by emson on Stack Overflow See other posts from Stack Overflow or by emson
Published on 2010-05-14T17:41:16Z Indexed on 2010/05/14 17:44 UTC
Read the original article Hit count: 427

Filed under:
|
|

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...

© Stack Overflow or respective owner

Related posts about ruby-on-rails

Related posts about mocking