[英]Testing POST #create in RSpec with nested attributes - can't get params hash correct
已经花了几个月的时间尝试使用RSpec / TDD。 在测试带有嵌套属性的控制器时遇到一些挑战。 我对如何正确设置参数并将参数传递给控制器有点模糊。 我可以构建控制器,使其实际上可以在浏览器中正常工作-我似乎无法对测试进行反向工程来确认这一点。
感谢您提出以下建议:a)修复以下测试,以及b)建议采取任何更好的方法(例如,使用模拟,存根等)。
这是基本的模型结构:
class School < ActiveRecord::Base
has_many :scholarships
end
class Scholarship < ActiveRecord::Base
belongs_to :school
end
我已经按照您的期望配置了route.rb:
resources :schools do
resources :scholarships, only: [:new, :create, :destroy]
end
在控制器中,#new和#create是Rails应用程序的标准配置:
class ScholarshipsController < ApplicationController
def new
@school = School.find(params[:school_id])
@scholarship = @school.scholarships.build
end
def create
@school = School.find(params[:school_id])
@scholarship = @school.scholarships.create(scholarship_params)
if @scholarship.save
flash[:success] = 'Scholarship created!'
redirect_to @school
else
render 'new'
end
end
private
def scholarship_params
params.require(:scholarship).permit(:name, ** Lots of params omitted for brevity **,
:notes, school: [:id])
end
end
我似乎无法弄清规范。 对于spec / controllers / scholarships_controller_spec.rb:
require 'rails_helper'
describe ScholarshipsController, type: :controller do
describe 'POST #create' do
context 'with valid attributes' do
before :each do
@school = create(:school)
@scholarship = @school.scholarships.create(FactoryGirl.build(:scholarship).attributes)
end
it 'receives :save' do
post :create, { scholarship: @scholarship.attributes, school: @school.id }
expect(@scholarship).to receive(:save)
end
end
end
end
运行该测试时,出现以下错误:
Failures:
1) ScholarshipsController POST #create with valid attributes receives :save
Failure/Error: post :create, scholarship: { attributes: @scholarship.attributes, school: @school.id } #school_id: @school.id, scholarship: @scholarship
ActionController::UrlGenerationError:
No route matches {:action=>"create", :controller=>"scholarships",
:scholarship=>{"id"=>"1", "name"=>"Dynamic Metrics Director Scholarship", *** Lots of parameters omitted for brevity ***
, "school_id"=>"2"}, :school=>"2"}
参数对我来说看起来正确。 奖学金和学校都有一套属性。 但是路由不起作用。 我尝试了十二种不同的方法来尝试使其正常工作。 令人鼓舞的是,我显然传递了(或多或少正确的)参数哈希,但无法弄清楚我要去哪里。
******编辑******
更新为响应下面发布的答案。 更改了Srdjan建议的规范语法:
it 'receives :save' do
post :create, "schools/#{@school.id}/scholarships", { scholarship: @scholarship.attributes, school_id: @school.id }
expect(@scholarship).to receive(:save)
end
这将更改错误消息。 我假设这表明参数已正确传递,因为它不再引发与路由/参数有关的错误。 错误信息是:
1) ScholarshipsController POST #create with valid attributes receives :save
Failure/Error: expect(@scholarship).to receive(:save)
(#<Scholarship:0x007fe293b02598>).save(*(any args))
expected: 1 time with any arguments
received: 0 times with any arguments
出于良好的考虑,以下是我之前未发布的相关路线:
school_scholarships POST /schools/:school_id/scholarships(.:format) scholarships#create
new_school_scholarship GET /schools/:school_id/scholarships/new(.:format) scholarships#new
school_scholarship DELETE /schools/:school_id/scholarships/:id(.:format) scholarships#destroy
在测试中,您正在张贴错误的路线。 作为routes.rb
设置,奖学金资源并不存在于学校资源的范围之外。
为了解决这个问题,您必须回答一个问题:“用户无需指定学校就可以访问奖学金记录吗?”
如果答案是肯定的,则您可以复制scholarships
途径并将其粘贴到schools
资源块之外。 这样,您无需指定学校,也可以指定学校而获得奖学金。
如果问题的答案为“否”,那么您需要像这样修复测试:
it 'receives :save' do post :create, "schools/#{@school.id}/scholarhips", { scholarship: @scholarship.attributes, school_id: @school.id } expect(@scholarship).to receive(:save) end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.