RSpec在Rails中模拟嵌套模型 - ActionController问题

时间:2010-05-14 17:41:16

标签: ruby-on-rails mocking rspec

当我的模拟对象被ActionController要求输入URL时,我在RSpec中遇到了问题。该URL是Mock,而不是正确的资源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

我的 routes.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 时,我收到以下错误:

  'NotesController中的 NoMethodError应该创建注释并重定向到没有javascript的主题'   未定义的方法`spec_mocks_mock_url'用于#&lt; NotesController:0x1034495b8&gt;

现在这是由一些传递ActiveRecord对象的Rails技巧引起的(在我们的例子中是@subject,它不是ActiveRecord而是Mock对象),最终传递给所有传递给所有人的 url_for Rails路由的选项,然后确定URL。

我的问题是如何模拟主题以便传递正确的选项以便我的测试通过。

我尝试传入:controller =&gt; '主题'选项,但没有快乐。

还有其他方法吗?

...谢谢

2 个答案:

答案 0 :(得分:2)

查看mock_model,它由rspec-rails添加,以便更容易模拟ActiveRecord对象。根据{{​​3}}:

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

我不确定它是否会照顾url_for,但值得一试。


更新,2018-06-05

api docs

  

mock_modelstub_model已被提取到As of rspec 3

答案 1 :(得分:0)

如果zetetic的想法没有成功,你可以随时说出Subject.new,然后将to_param以及你可能需要伪造的其他任何内容用于你的例子。