我有以下规格:
# 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。
答案 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)它很脆弱:
User
和视图时,测试可能会中断。假设您正在添加一个字段 - 网站。如果只是在数据库和视图中添加该列,则测试将失败,因为它尝试访问不存在的(在存根中)列。现在你有了工作代码,但是测试失败了。您必须在存根中添加:website
。这只是打破它的方法之一。根据我的经验,经常发生的情况是,当代码工作时,视图规范很容易破坏。当你依赖助手时,这是双重麻烦。我发现他们只有一个值 - 测试驱动非ActiveRecord :: Object的接口。您使用模拟构建视图test-first。完成后,您就知道模型需要哪些方法。
我更喜欢的替代方案是在集成中测试那些东西。我个人使用黄瓜,虽然牛排也很好。它为您提供更好的覆盖范围和更低的脆弱性。根据我的观察,在rspec邮件列表中,查看规范已经有点过时了。您可以搜索它以获取有关避免它们的原因的更多详细信息。这是我one thread的一些观点。
最后,如果我无法说服你放弃这条道路,请查看factory_girl。它提供了一个称为build_stubbed
的简洁方法,它为您提供了可以在form_for
中使用的存根模型。虽然我已经使用了几次,但我后来总是后悔。
当然,YMMV。