Rspec& FactoryGirl:它是否真的将用户ID分配给我的模型?

时间:2012-09-10 17:53:11

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

以下是我的工厂:

规格/ factories.rb

FactoryGirl.define do
  factory :user do
    username   'user1'
    time_zone  'Eastern Time (US & Canada)'
    email      'user@example.com'
    password   'testing'
  end

  factory :product do
    name 'Great Product'
    about 'this is stuff about the product'
    private false
  end
end

我的产品型号:

模型/ product.rb

class Product < ActiveRecord::Base
  attr_accessible :about, :name, :private
  belongs_to :user
  has_many :prices
  validates_presence_of :name
  validates_presence_of :user_id
end

这是我使用Rspec和Shoulda求助的测试:

规格/模型/ product_spec.rb

require 'spec_helper'

describe Product do
  before(:each) do
    FactoryGirl.build(:product)
  end

  it { should have_many(:prices) }
  it { should belong_to(:user) }

  it { should validate_presence_of :name }
  it { should validate_presence_of :user_id }
end

测试通过,但我认为我想为协会做这件事:

factory :product do
    name 'Great Product'
    about 'this is stuff about the product'
    private false

    user # <--
end

如果我使用错误执行此操作,所有测试都将失效:

ActiveRecord::RecordInvalid:
       Validation failed: Time zone is not included in the list

那么它是否真的指派了我在工厂创建的用户?

修改

User.rb

  has_many :products

  validates_presence_of :username
  validates_presence_of :time_zone
  validates_format_of :username, :with => /^(?=(.*[a-zA-Z]){3})[a-zA-Z0-9]+$/
  validates_uniqueness_of :email         
  validates_uniqueness_of :username, :case_sensitive => false
  validates_length_of :username, :within => 3..26
  validates_inclusion_of :time_zone, :in => ActiveSupport::TimeZone.us_zones

2 个答案:

答案 0 :(得分:1)

您的验证失败导致您在工厂中使用错误的时区

1.9.3p194 :009 > ActiveSupport::TimeZone.us_zones
=> [(GMT-10:00) Hawaii, (GMT-09:00) Alaska, (GMT-08:00) Pacific Time (US & Canada), (GMT-07:00) Arizona, (GMT-07:00) Mountain Time (US & Canada), (GMT-06:00) Central Time (US & Canada), (GMT-05:00) Eastern Time (US & Canada), (GMT-05:00) Indiana (East)]

1.9.3p194 :010 > ActiveSupport::TimeZone.us_zones.include?('Eastern Time (US & Canada)')
=> false 

您应该在工厂中使用

之类的东西
ActiveSupport::TimeZone.create("Eastern Time (US & Canada)")

如果您希望验证通过。

或者如果您想将时区存储在数据库中的字符串值中,您应该将代码更改为此类

# user.rb
...
validates_inclusion_of :time_zone, :in => ActiveSupport::TimeZone.us_zones.map(&:to_s)

# spec/factories.rb
...
time_zone  "(GMT-05:00) Eastern Time (US & Canada)"
...

答案 1 :(得分:1)

当你这样做时

  it { should validate_presence_of :user_id }

应验证当user_id缺失时,您的模型无效并且错误列表包含带有相应消息的user_id错误。对象最初是否有效(或者在其他属性上有错误)是无关紧要的:这就是为什么当您的工厂没有将用户分配给产品时您的测试通过

我怀疑你的其他测试失败了,因为你正在测试在时区对象数组中包含字符串(time_zone) - 'Eastern Time (US & Canada)'不等于相应的时区对象(很像"1" != 1