【问题标题】:FactoryGirl and RspecFactoryGirl 和 Rspec
【发布时间】:2011-12-08 23:40:55
【问题描述】:

我对这个 TDD 业务非常熟悉,所以任何帮助都会很棒!

所以,我有一个工厂,有以下内容:

FactoryGirl.define do

  factory :account do
    email "example@example.com"
    url "teststore"
  end  

end

还有一个 Rspec 测试:

  it "fails validation without unique email" do
    account1 = FactoryGirl.create(:account)
    account2 = FactoryGirl.create(:account)
    account2.should have(1).error_on(:email)
end

我收到以下消息失败:

  1) Account fails validation without unique email
     Failure/Error: account2 = FactoryGirl.create(:account)
     ActiveRecord::RecordInvalid:
       Validation failed: Email taken, please choose another, Url taken, please choose another
     # ./spec/models/account_spec.rb:11:in `block (2 levels) in <top (required)>'

这是创建新工厂的正确方法吗?任何想法我在这里做错了什么(我毫不怀疑我在做某事完全不正确!)

编辑:我想代替在第二个帐户上使用“创建”,我可能想使用 .build 然后 .save 代替?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 rspec tdd factory-bot


    【解决方案1】:

    为自己保存数据库交互并在这种情况下使用build 方法。

    it "fails validation without unique email" do
      account1 = create(:account)
      account2 = build(:account)
      account2.should_not be_valid
      account2.should have(1).error_on(:email) 
    end
    

    您无需尝试为 valid? 创建帐户即可返回 false。即使只是在内存中构建,您也可以访问帐户上的错误对象。这将减少数据库交互,从而使您的测试更快。

    您是否考虑过在您的工厂中使用序列?我不知道您的 RSpec / FactoryGirl 体验进展如何,但您会发现以下内容非常有用。

    factories.rb

    factory :account do
      sequence(:email) { |n| "user#{n}@example.com" }
      url "teststore"
    end
    

    每次在账号工厂拨打buildcreate,都会收到独一无二的邮件。

    请记住,您始终可以使用选项哈希为工厂的属性指定值。因此,在测试您对帐户的唯一性验证时,您会执行以下操作。

    it "fails validation without unique email" do
      account1 = create(:account, :email => "foo@bar.com")
      account2 = build(:account, :email => "foo@bar.com")
      account2.should_not be_valid
      account2.should have(1).error_on(:email) 
    end
    

    【讨论】:

    • 很抱歉,如果这看起来很密集,但这不会通过测试,因为“序列”会创建两封不同的电子邮件吗?
    • 太棒了,正是我所追求的。感谢您的帮助 - 我期待着新的激动人心的测试世界!
    • 很高兴我能帮上忙。当我第一次开始测试时,它似乎在应用程序的开始阶段减慢了我的开发时间。只要坚持下去,记住它将为您节省多少时间。
    【解决方案2】:

    试试这个:

    FactoryGirl.create(:account)
    lambda {
      FactoryGirl.create(:account)
    }.should raise_error(ActiveRecord::RecordInvalid)
    

    这将有所帮助 - 语法与您正在做的事情相似。

    但是,搜索“rspec validate_uniqueness_of”会发现一些更优雅的方法,而不是像这样使用工厂女孩!

    【讨论】:

    • 查看“Shouda Matchers”宝石;它会为您节省一些输入:github.com/thoughtbot/shoulda-matchers
    • 公平地说这是一个毫无意义的测试,因为我真的只是在测试内置于 rails 的验证吗? (即不是我自己的代码)
    • 这个测试不是没有意义的。您正在测试在 Account 模型 (:uniqueness =&gt; true) 上设置的验证。如果您(或其他开发人员)删除此验证,您的测试将失败。
    • 这是一个非常有意义的测试。再次搜索测试此行为将引起您的注意。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-18
    相关资源
    最近更新 更多