RSpec макетирует вложенную модель в Rails - проблема ActionController - PullRequest
1 голос
/ 14 мая 2010

У меня проблема в RSpec, когда мой фиктивный объект запрашивает URL-адрес ActionController. URL является ложным, а не правильным URL ресурса.

Я использую RSpec 1.3.0 и Rails 2.3.5

В основном у меня есть две модели. Там, где у предмета много заметок.

class Subject < ActiveRecord::Base
  validates_presence_of :title
  has_many :notes
end

class Note < ActiveRecord::Base
  validates_presence_of :title
  belongs_to :subject
end

Мой rout.rb файл объединяет эти два ресурса следующим образом:

ActionController::Routing::Routes.draw do |map|
  map.resources :subjects, :has_many => :notes
end

Файл NotesController.rb выглядит следующим образом:

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

Наконец, это моя спецификация RSpec, которая должна просто публиковать мои макетированные объекты в NotesController и выполняться ... что он делает:

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

Проблема в том, что когда вызывается RSpec post метод.

NotesController правильно обрабатывает объект Mock Subject, и создает! новый Note объект. Однако, когда метод NoteController # Create пытается redirect_to , я получаю следующую ошибку:

NoMethodError в 'NotesController должен создавать заметки и перенаправлять на тему без JavaScript' неопределенный метод `spec_mocks_mock_url 'для #

Теперь это вызвано небольшим обманом Rails, который передает объект ActiveRecord (в нашем случае @subject, который не ActiveRecord, а объект Mock), в конечном итоге url_for , который передает все опции для маршрутизации Rails, которая затем определяет URL.

У меня вопрос, как я могу издеваться над субъектом, чтобы передать правильные параметры, чтобы я сдал тест?

Я пытался передать : controller => 'subject' опции, но без радости.

Есть ли другой способ сделать это?

Спасибо ...

Ответы [ 2 ]

2 голосов
/ 14 мая 2010

Взгляните на mock_model, который добавлен rspec-rails, чтобы упростить имитацию объектов ActiveRecord. Согласно api docs :

mock_model: Creates a mock object instance for a model_class with common methods stubbed out.

Я не уверен, что он позаботится о url_for, но стоит попробовать.


Обновление, 2018-06-05 :

По состоянию на rspec 3 :

mock_model и stub_model были извлечены в rspec-activemodel-mocks gem .

0 голосов
/ 15 мая 2010

Если идея Zetetic не сработает, вы всегда можете сказать Subject.new, а затем заглушить to_param и все, что вам может понадобиться, подделать для вашего примера.

...