RSpec + 表单对象 + 简单表单给出未定义的方法

瑞吉

我正在尝试对控制器的规范进行一些嘲笑。当我发布有效文章时,我已经编写了适用于这种情况的代码,但是当我尝试指定不应保存它时,我遇到了错误。

我的代码:

文章形式:

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

文章控制器(仅创建操作):

  def create
    @article_form = ArticleForm.new
    if @article_form.save(article_params)
      flash[:notice] = 'You have added a new article.'
      redirect_to @article_form.article
    else
      flash[:danger] = 'Failed to add new article.'
      render :new
    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 用户登录 POST 文章#create 用户添加无效文章呈现新表单 出现 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'

我很少尝试通过允许对象接收它来添加缺少的方法,但这是一件好事吗?以后我必须允许每次调用(当我允许 param_keys 时,它会询问 _form 的所有值 - 标题、正文和标签)。有没有办法让它在不逐行指定所有方法的情况下工作?

劳拉·帕基宁

Rails 中的控制器测试用于“功能”测试这意味着他们测试发送到应用程序的请求的多层。

因此,基本上您正在尝试测试处理请求所涉及的所有部分是否有效。因此,在这些类型的测试中不希望使用模拟和存根,因为您试图使测试尽可能“真实”。我建议实例化一个真实的ArticleForm对象,而不是创建一个实例 double。

let(:article_form) { ArticleForm.new(article) } 

通过这种方式,您还可以测试ArticleForm实例。在某些情况下,存根或article_form模拟在控制器测试中也有意义,但在您的情况下,实例是测试的核心,因此使用模拟意味着大量的工作,并且测试将变得更加复杂.

如果你想尝试模拟,一个更好的起点可以是例如查看规范

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Rails表单给出了未定义的方法错误

来自分类Dev

RSpec NoMethodError:“主对象的未定义方法'描述'”

来自分类Dev

表单提交给出未定义的值

来自分类Dev

表单助手未定义方法

来自分类Dev

在表单提交事件对象上给出错误:“ TypeError:无法从未定义中读取属性” 0“。

来自分类Dev

尝试创建表单以更新多个对象时出现“(未定义的局部变量或方法”)错误

来自分类Dev

表单输入未定义

来自分类Dev

Rspec-未定义的方法'let'

来自分类Dev

#<RSpec的未定义方法`get'

来自分类Dev

Rspec未定义方法“至”

来自分类Dev

Rspec未定义方法“匹配?” 错误

来自分类Dev

Rspec未定义方法“至”

来自分类Dev

RSpec-未定义的方法“键?”

来自分类Dev

NoMethodError:RSpec 的未定义方法“get”

来自分类Dev

RSpec:#<RSpec :: Core :: ExampleGroup :: Nested的未定义方法'allow'

来自分类Dev

RSpec 存根服务对象方法

来自分类Dev

使用RSpec测试多步骤表单

来自分类Dev

呈现部分表单时的未定义方法

来自分类Dev

Rails更新表单抛出“ nil:NilClass的未定义方法'[]'”

来自分类Dev

javascript-打印表单值到console.log给出未定义的错误

来自分类Dev

对象数组给出未定义

来自分类Dev

访问json对象给出未定义

来自分类Dev

简单的表单验证帮助“无法读取未定义的属性'elements'”

来自分类Dev

表单提交时未定义的索引

来自分类Dev

Webix表单getValues()返回未定义

来自分类Dev

表单动作内容返回未定义

来自分类Dev

为什么表单输入未定义?

来自分类Dev

nodejs的“ POST”表单未定义

来自分类Dev

jQuery表单验证“未定义”