我正在尝试在我的多态评论 Controller 中测试 POST 创建操作。当运行下面的规范时,它们失败并出现错误:
undefined method `comments' for nil:NilClass
我认为这意味着@commentable 没有被正确创建/设置,所以它不存在。 ATM 我正在删除 load_commentable
方法并返回 FactoryGirl 问题对象,但这似乎仍然没有解决任何问题。
如何修改我的规范,以便正确创建可评论对象,并在@commentable 范围内创建评论,就像在实际 Controller 中一样?
评论 Controller .rb
def create
@comment = @commentable.comments.build(params[:comment])
@comment.user_id = current_user.id
respond_to do |format|
if @comment.save
format.html { redirect_to @commentable, notice: 'Comment created'}
format.js
else
format.html { redirect_to @commentable, notice: "Content can't be blank" }
format.js
end
end
end
def load_commentable
resource, id = request.path.split('/')[1,2]
@commentable = resource.singularize.classify.constantize.find(id)
end
comments_controller_spec.rb
describe CommentsController do
include Devise::TestHelpers
include AnswerHelper
before(:each) do
@user = create(:user)
@user2 = create(:user)
sign_in @user
sign_in @user2
@commentable = create(:question, user: @user2)
@comment = create(:comment, user: @user)
@vote = attributes_for(:vote, user: @user2, votable_id: @commentable)
controller.stub!(:load_commentable).and_return(@commentable)
controller.stub!(:current_user).and_return(@user)
@request.env['HTTP_REFERER'] = "http://test.host/questions/#{@commentable.id}"
stub_model_methods
end
describe "POST create" do
describe "with valid params" do
it "creates a new comment" do
expect {
post :create, comment: attributes_for(:comment), commentable: @commentable
}.to change(Comment, :count).by(1)
end
it "assigns a newly created comment as @comment" do
post :create, comment: attributes_for(:comment), commentable: @commentable
assigns(:comment).should be_a(Comment)
assigns(:comment).should be_persisted
end
end
describe "with invalid params" do
it "assigns a newly created but unsaved comment as @comment" do
Comment.any_instance.stub(:save).and_return(false)
post :create, comment: attributes_for(:comment), commentable: @commentable
assigns(:comment).should be_a_new(Comment)
end
end
end
工厂.rb
factory :comment do
user
commentable_id :question
commentable_type "Question"
content "a comment"
votes_count 5
end
rspec 结果
1) CommentsController POST create with valid params creates a new comment
Failure/Error: post :create, comment: attributes_for(:comment), commentable: @commentable
NoMethodError:
undefined method `comments' for nil:NilClass
# ./app/controllers/comments_controller.rb:19:in `create'
# ./spec/controllers/comments_controller_spec.rb:24:in `block (5 levels) in <top (required)>'
# ./spec/controllers/comments_controller_spec.rb:23:in `block (4 levels) in <top (required)>'
最佳答案
这里的问题是您正在删除 load_commentable,它负责在您的 Controller 中设置实例变量 @commentable
。因为你在 stub ,它永远不会被调用,而且 ivar 永远不会被设置 - 你不能直接从你的 rspec 测试套件在你的 Controller 中设置 ivars。
由于您正在创建一条记录,因此您实际上不需要 stub 任何东西,只需传递 @commentable.id
,然后让它从数据库中查找即可。但是,如果你出于某种原因想避免查找,你可以使用:
Question.stub(:find).with(@commentable.id).and_return(@commentable)
这将导致您的 Controller 使用您的@commentable
对象,并将其分配给 Controller 中的@commentable
,此时测试应该会继续正常运行。
关于ruby-on-rails - 测试多态注释 Controller Rspec 中的创建操作 - 未定义方法 `comments' 为 nil :NilClass,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17381335/