【问题标题】:RSpec-rails | Password field doesn't require the appropriate attribute for the modelRSpec-rails |密码字段不需要模型的适当属性
【发布时间】:2012-01-27 17:59:10
【问题描述】:

我有以下规格:

# spec/views/users/new.html.haml

require 'spec_helper'

describe 'users/new' do
  before { assign :user, stub_model(User).as_new_record }
  before { render }

  subject { rendered }

  it { should have_selector "form input[type=\"text\"][name=\"user[email]\"]" }
  it { should have_selector "form input[type=\"password\"][name=\"user[password]\"]" }
end

当我在创建表单后运行它时,它抱怨未定义的方法“电子邮件”:

undefined method `email' for #<User ...>

如果我将此方法添加到用户,则在用户表中创建适当的列或存根示例中的方法,两个示例都已通过,尽管 密码 方法是仍然未定义。

为什么第二个例子通过了?

谢谢。

红宝石 1.9.3;

Ruby on Rails 3.2.1;

RSpec 2.8.0;

RSpec-rails 2.8.1.

【问题讨论】:

  • 可以添加 User 类的代码吗?您使用的是什么身份验证库?
  • 在这个例子中我不使用任何授权库。无论如何调用属性:如果我在模型中指定第一个属性,则两个示例都会通过。

标签: ruby-on-rails rspec rspec-rails


【解决方案1】:

棘手的问题。首先,我将尝试解释您正在观察的行为。然后我会争辩说这不应该是一个视图规范,并详细说明我相信的替代方案。最后我会告诉你如何才能真正让它工作。

当您在视图规范中呈现表单字段时,代码取决于具有所有属性的模型。 text_field 调用 User#login 来填写表单值(如果应该有的话)。 password_field 不会,因为您不希望预先填写密码字段。这就是它们在规范之外的工作方式,这几乎是预期的行为。这就是你得到这种行为的原因。

至于视图规格,这个不是很有用。两个原因 - (1) 它不会增加价值和 (2) 它很脆弱:

  1. 本规范中指定的唯一知识是存在两个输入字段。这无助于您推动设计或发现行为。此外,它不能保护您免受可能的错误的影响。您可以防止的唯一错误是意外删除表单。在我看来,这极不可能。在集成测试中测试提交表单应该做什么会更好(比如 Cucumber 或 Steak)
  2. 由于存在存根,当您扩展 User 和视图时,测试可能会中断。假设您要添加一个字段 - 网站。如果您只是在数据库和视图中添加列,则测试将失败,因为它会尝试访问不存在的(在存根中)列。现在您有工作代码,但测试失败。您必须在存根中添加:website。这只是打破它的方法之一。根据我的经验,当代码正常工作时,视图规范很容易被破坏。当您依赖助手时,麻烦会加倍。

我发现它们只有一个值——测试驱动非 ActiveRecord::Object 的接口。您首先使用模拟构建视图测试。完成后,您就知道模型需要哪些方法。

我更喜欢的替代方法是在集成中测试这些东西。我个人用黄瓜,虽然牛排也很好。它为您提供更好的覆盖范围和更少的脆弱性。在我的观察中,视图规范在 rspec 邮件列表中有点失宠。您可以搜索它以获取有关为什么要避免它们的更多详细信息。这是one thread,我分享了我的一些观点。

最后,如果我未能说服您放弃这条道路,请查看factory_girl。它提供了一个简洁的方法,称为build_stubbed,它为您提供了一个可以在form_for 中使用的存根模型。虽然我用过几次,但后来总是后悔。

当然,YMMV。

【讨论】:

    【解决方案2】:

    事实证明,当 Rails 为模型的属性创建 文本字段 时,模型应该具有该属性。如果没有,则在尝试呈现表单时会出现 ActionView::Template::Error。然而,当 Rails 创建一个密码字段时,模型不应该有适当的属性,所以在渲染表单时什么都不会上升。

    因此,如果我指定某个视图应该有一个模型属性的文本字段,那么示例将需要该属性。相反,当我为某个属性指定某个视图应该有一个密码字段时,该示例不会要求驱除该属性。

    例如:

    = form_for @user do |f|
      %div= f.text_field :login #=> User#login is required
      %div= f.password_field :password #=> User#password isn't requred
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-12
      • 2011-01-03
      • 2012-09-03
      • 2020-04-26
      • 2010-11-30
      • 1970-01-01
      • 2021-02-09
      • 2021-06-18
      相关资源
      最近更新 更多