我正在通过为现有项目编写规范来学习RSpec。我遇到了多态资源Notes的控制器规范。事实上,任何其他模型都可以与Notes建立关系:has_many :notes, as: :noteable
此外,该应用程序是多租户,每个帐户可以拥有多个用户。每个帐户都可以通过网址:slug
而不是:id
进行访问。所以我的多租户,多态路由看起来像这样:
# config/routes.rb
...
scope ':slug', module: 'accounts' do
...
resources :customers do
resources :notes
end
resources :products do
resources :notes
end
end
这会产生以下路线:新行动
new_customer_note GET /:slug/customers/:customer_id/notes/new(.:format) accounts/notes#new
new_product_note GET /:slug/products/:product_id/notes/new(.:format) accounts/notes#new
现在谈到测试问题。首先,这是我如何测试其他非多态控制器的示例,例如invitations_controller:
# from spec/controllers/accounts/invitation_controller_spec.rb
require 'rails_helper'
describe Accounts::InvitationsController do
describe 'creating and sending invitation' do
before :each do
@owner = create(:user)
sign_in @owner
@account = create(:account, owner: @owner)
end
describe 'GET #new' do
it "assigns a new Invitation to @invitation" do
get :new, slug: @account.slug
expect(assigns(:invitation)).to be_a_new(Invitation)
end
end
...
end
当我尝试使用类似的方法来测试多态性notes_controller时,我感到困惑: - )
# from spec/controllers/accounts/notes_controller_spec.rb
require 'rails_helper'
describe Accounts::NotesController do
before :each do
@owner = create(:user)
sign_in @owner
@account = create(:account, owner: @owner)
@noteable = create(:customer, account: @account)
end
describe 'GET #new' do
it 'assigns a new note to @note for the noteable object' do
get :new, slug: @account.slug, noteable: @noteable # no idea how to fix this :-)
expect(:note).to be_a_new(:note)
end
end
end
这里我只是在前面的块中创建一个名为@noteable的客户,但它也可以是一个产品。当我运行rspec时,我收到此错误:
No route matches {:action=>"new", :controller=>"accounts/notes", :noteable=>"1", :slug=>"nicolaswisozk"}
我看到问题所在,但我无法弄清楚如何处理网址的动态部分,例如/products/
或/customers/
。
感谢任何帮助: - )
更新
根据以下要求将get :new
行更改为
get :new, slug: @account.slug, customer_id: @noteable
,这会导致错误
Failure/Error: expect(:note).to be_a_new(:note)
TypeError:
class or module required
# ./spec/controllers/accounts/notes_controller_spec.rb:16:in `block (3 levels) in <top (required)>'
规范中的第16行是:
expect(:note).to be_a_new(:note)
这可能是因为我的notes_controller.rb中的:new操作不只是@note = Note.new
,而是在@noteable上初始化一个新的注释,就像这样?:
def new
@noteable = find_noteable
@note = @noteable.notes.new
end
答案 0 :(得分:2)
这里的问题应该是在这一行
get :new, slug: @account.slug, noteable: @noteable
你正在:noteable
传递参数。但是,您需要传递url的所有动态部分,以帮助rails匹配路由。在这里你需要通过:customer_id
参数。像这样,
get :new, slug: @account.slug, customer_id: @noteable.id
如果有帮助,请告诉我。