Ruby on rails RSpec+;表单对象+;简单形式给出了未定义的方法
我正在尝试为控制器做一些规格的模拟。当我发布有效的文章时,我编写的代码可以很好地处理这种情况,但是当我试图指定不应该保存它时,我会遇到错误 我的代码: 条款形式:Ruby on rails RSpec+;表单对象+;简单形式给出了未定义的方法,ruby-on-rails,rspec,simple-form,Ruby On Rails,Rspec,Simple Form,我正在尝试为控制器做一些规格的模拟。当我发布有效的文章时,我编写的代码可以很好地处理这种情况,但是当我试图指定不应该保存它时,我会遇到错误 我的代码: 条款形式: class ArticleForm include ActiveModel::Model delegate :title, :body, :author_id, :tags, :id, :persisted?, :new_record?, to: :article attr_accessor :article, :tags
class ArticleForm
include ActiveModel::Model
delegate :title, :body, :author_id, :tags, :id, :persisted?, :new_record?, to: :article
attr_accessor :article, :tags_string
validates :title, :body, :tags, presence: true
validates_length_of :title, within: 8..512
validates_length_of :body, within: 8..2048
validate :validate_prohibited_words
def initialize(article = Article.new)
@article = article
end
def save(article_params)
assign_params_to_article(article_params)
if valid?
@article.tags.each(&:save!)
@article.save!
true
else
false
end
end
...
end
项目控制器(仅创建操作):
_表格:
= simple_form_for @article_form,
url: (@article_form.article.new_record? ? articles_path : article_path(@article_form.article) ) do |f|
= f.input :title, label: "Article title:"
= f.input :body, label: "Body of the article:", as: :text, input_html: { :style => 'height: 200px' }
= f.input :tags_string, label: "Tags:", input_html: { value: f.object.all_tags }
= f.button :submit, 'Send!'
物品控制器规格:
require 'rails_helper'
RSpec.describe ArticlesController, type: :controller do
render_views
let!(:user) { create(:user) }
let!(:tag) { create(:tag) }
let(:tags_string) { 'test tag' }
let!(:article) { create(:article, :with_comments, tags: [tag], author_id: user.id) }
context 'user logged in' do
before { sign_in(user) }
describe 'POST artictles#create' do
let(:article_form) { instance_double(ArticleForm) }
let(:form_params) do
{
article_form:
{
title: 'title',
body: 'body',
tags_string: tags_string
}
}
end
context 'user adds valid article' do
it 'redirects to new article', :aggregate_failures do
expect(ArticleForm).to receive(:new).and_return(article_form)
expect(article_form).to receive(:save).with(hash_including(:author_id, form_params[:article_form]))
.and_return(true)
allow(article_form).to receive(:article) { article }
post :create, params: form_params
expect(response).to redirect_to(article)
end
end
context 'user adds invalid article' do
it 'renders new form', :aggregate_failures do
expect(ArticleForm).to receive(:new).and_return(article_form)
allow(article_form).to receive(:article) { article }
expect(article_form).to receive(:save).with(hash_including(:author_id, form_params[:article_form]))
.and_return(false)
post :create, params: form_params
expect(response).to render_template(:new)
end
end
end
end
end
发布有效作品很好,这是我在“无效帖子”上遇到的错误:
失败:
1) ArticlesController用户登录文章后#创建用户添加
无效文章呈现新形式
得到1个失败和1个其他错误:
1.1) Failure/Error: = simple_form_for @article_form,
#<InstanceDouble(ArticleForm) (anonymous)> received unexpected message :model_name with (no args)
# ./app/views/articles/_form.html.haml:2:in `_app_views_articles__form_html_haml__2443549359101958040_47338976410880'
# ./app/views/articles/new.html.haml:2:in `_app_views_articles_new_html_haml___678894721646621807_47338976253400'
# ./app/controllers/articles_controller.rb:26:in `create'
# ./spec/controllers/articles_controller_spec.rb:51:in `block (5 levels) in <top (required)>'
1.2) Failure/Error: = simple_form_for @article_form,
ActionView::Template::Error:
undefined method `param_key' for #<Array:0x0000561bedbcd888>
# ./app/views/articles/_form.html.haml:2:in `_app_views_articles__form_html_haml__2443549359101958040_47338976410880'
# ./app/views/articles/new.html.haml:2:in `_app_views_articles_new_html_haml___678894721646621807_47338976253400'
# ./app/controllers/articles_controller.rb:26:in `create'
# ./spec/controllers/articles_controller_spec.rb:51:in `block (5 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# NoMethodError:
# undefined method `param_key' for #<Array:0x0000561bedbcd888>
# ./app/views/articles/_form.html.haml:2:in `_app_views_articles__form_html_haml__2443549359101958040_47338976410880'
1.1)失败/错误:=简单的@article\u表单,
#收到意外消息:型号名称(无参数)
#/app/views/articles/_form.html.haml:2:in`` app\u views\u articles\u form\u html\u haml\u 24435493595101958040\u 47338976410880'
#/app/views/articles/new.html.haml:2:in``应用程序视图文章新html\u haml\u 678894721646621807\u 47338976253400'
#/app/controllers/articles\u controller.rb:26:in'create'
#./spec/controllers/articles\u controller\u spec.rb:51:in'block(5级)in'
1.2)失败/错误:=简单形式@物品形式,
ActionView::模板::错误:
未定义的方法“param_key”#
#/app/views/articles/_form.html.haml:2:in`` app\u views\u articles\u form\u html\u haml\u 24435493595101958040\u 47338976410880'
#/app/views/articles/new.html.haml:2:in``应用程序视图文章新html\u haml\u 678894721646621807\u 47338976253400'
#/app/controllers/articles\u controller.rb:26:in'create'
#./spec/controllers/articles\u controller\u spec.rb:51:in'block(5级)in'
# ------------------
#---原因:---
#命名错误:
#未定义的方法“param_key”#
#/app/views/articles/_form.html.haml:2:in`` app\u views\u articles\u form\u html\u haml\u 24435493595101958040\u 47338976410880'
我很少尝试通过允许对象接收来添加缺少的方法,但这是一件好事吗?以后我必须允许每次调用(当我允许param_键时,它会要求为_表单提供所有值-title、body和tags)。有没有一种方法可以让它在不逐行指定所有方法的情况下工作?使用Rails中的控制器测试。这意味着它们测试发送到应用程序的请求的几个层次 因此,基本上,您正在尝试测试处理请求所涉及的所有部分是否正常工作。因此,在这类测试中不需要使用mock和stub,因为您正试图使测试尽可能“真实”。我建议实例化一个real
ArticleForm
对象,而不是创建一个双实例
let(:article_form) { ArticleForm.new(article) }
这样,您也可以测试ArticleForm
实例。有些情况下,在控制器测试中,存根或模拟也有意义,但在您的情况下,文章表单
实例是测试的核心,因此使用模拟意味着大量的工作,测试将变得更加复杂
如果你想尝试模仿,一个更好的起点可以是例如
let(:article_form) { ArticleForm.new(article) }