RSpec:具有多态资源的控制器规范,"No route matches" 错误
RSpec: Controller spec with polymorphic resource, "No route matches" error
我正在通过为现有项目编写规范来学习 RSpec。我在使用多态资源 Notes 的控制器规范时遇到问题。实际上,任何其他模型都可以像这样与 Notes 建立关系:has_many :notes, as: :noteable
此外,该应用程序是多租户的,每个帐户可以有多个用户。 URL 中的每个帐户都由 :slug
而不是 :id
访问。所以我的多租户多态路由看起来像这样:
# config/routes.rb
...
scope ':slug', module: 'accounts' do
...
resources :customers do
resources :notes
end
resources :products do
resources :notes
end
end
这会导致 :new 操作的路由与此类似
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"}
我明白问题出在哪里了,但我就是想不出如何解决 URL 的动态部分,例如 /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 上初始化一个新的 Note,就像这样?:
def new
@noteable = find_noteable
@note = @noteable.notes.new
end
那么这里的问题应该是在这一行
get :new, slug: @account.slug, noteable: @noteable
您正在传递 :noteable
参数。但是,您需要传递 url 的所有动态部分,以帮助 rails 匹配路由。这里需要在params中传递:customer_id
。像这样,
get :new, slug: @account.slug, customer_id: @noteable.id
如果有帮助,请告诉我。
我正在通过为现有项目编写规范来学习 RSpec。我在使用多态资源 Notes 的控制器规范时遇到问题。实际上,任何其他模型都可以像这样与 Notes 建立关系:has_many :notes, as: :noteable
此外,该应用程序是多租户的,每个帐户可以有多个用户。 URL 中的每个帐户都由 :slug
而不是 :id
访问。所以我的多租户多态路由看起来像这样:
# config/routes.rb
...
scope ':slug', module: 'accounts' do
...
resources :customers do
resources :notes
end
resources :products do
resources :notes
end
end
这会导致 :new 操作的路由与此类似
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"}
我明白问题出在哪里了,但我就是想不出如何解决 URL 的动态部分,例如 /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 上初始化一个新的 Note,就像这样?:
def new
@noteable = find_noteable
@note = @noteable.notes.new
end
那么这里的问题应该是在这一行
get :new, slug: @account.slug, noteable: @noteable
您正在传递 :noteable
参数。但是,您需要传递 url 的所有动态部分,以帮助 rails 匹配路由。这里需要在params中传递:customer_id
。像这样,
get :new, slug: @account.slug, customer_id: @noteable.id
如果有帮助,请告诉我。