RSpec-rails |密码字段不需要模型的相应属性

时间:2012-01-27 17:59:11

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

我有以下规格:

# 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

当我在创建表单后运行它时,它会抱怨未定义的方法'email':

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

如果我将此方法添加到User,请在users表中创建相应的列,或者在示例中创建方法,两个示例都已传递,尽管密码方法是仍未定义。

为什么传递第二个例子?

感谢。

Ruby 1.9.3;

Ruby on Rails 3.2.1;

RSpec 2.8.0;

RSpec-rails 2.8.1。

2 个答案:

答案 0 :(得分:0)

事实证明,当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

答案 1 :(得分:0)

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

在视图规范中渲染表单域时,代码取决于具有所有属性的模型。 text_field调用User#login填写表单值,如果有的话。 password_field没有,因为您不希望预先填写密码字段。这就是他们如何在规范之外工作,这是非常期待的行为。这就是你获得这种行为的原因。

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

  1. 此规范中指定的唯一知识是存在两个输入字段。这无助于您推动设计或发现行为。此外,它不会保护您免受可能的错误。您可以阻止的唯一错误是意外删除表单。在我看来,这是不太可能的。更好的方法是测试提交表单应该在集成测试中做什么(比如Cucumber或Steak)
  2. 由于存根,当您扩展User和视图时,测试可能会中断。假设您正在添加一个字段 - 网站。如果只是在数据库和视图中添加该列,则测试将失败,因为它尝试访问不存在的(在存根中)列。现在你有了工作代码,但是测试失败了。您必须在存根中添加:website。这只是打破它的方法之一。根据我的经验,经常发生的情况是,当代码工作时,视图规范很容易破坏。当你依赖助手时,这是双重麻烦。
  3. 我发现他们只有一个值 - 测试驱动非ActiveRecord :: Object的接口。您使用模拟构建视图test-first。完成后,您就知道模型需要哪些方法。

    我更喜欢的替代方案是在集成中测试那些东西。我个人使用黄瓜,虽然牛排也很好。它为您提供更好的覆盖范围和更低的脆弱性。根据我的观察,在rspec邮件列表中,查看规范已经有点过时了。您可以搜索它以获取有关避免它们的原因的更多详细信息。这是我one thread的一些观点。

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

    当然,YMMV。