FactoryGirl + Rspec 自定义验证测试

FactoryGirl + Rspec custom validation test

我对测试还很陌生。

我在个人资料模型中进行了自定义验证

def birth_date_cannot_be_in_the_future
    errors.add(:birth_date, "the birth date cannot be in the future") if
    !birth_date.blank? && birth_date > Date.today
end

在我的factories.rb

sequence(:email) {|n| "person-#{n}@example.com"}
factory :user do
  email
  password 'password'
  password_confirmation 'password'
  confirmed_at Time.now
end

factory :profile do
  user
  first_name { "User" }
  last_name { "Tester" }
  birth_date { 21.years.ago }
end

在我的 models/profile_spec.rb

it 'birth date cannot be in the future' do
    profile = FactoryGirl.create(:profile, birth_date: 100.days.from_now)
    expect(profile.errors[:birth_date]).to include("the birth date cannot be in the future")
    expect(profile.valid?).to be_falsy
end

当我 运行 我的测试时,我收到以下消息:

Failure/Error: profile = FactoryGirl.create(:profile, birth_date: 100.days.from_now)

 ActiveRecord::RecordInvalid:
   The validation fails: Birth date the birth date cannot be in the future

我做错了什么?

有一个匹配器专门用于捕获错误。没有测试,我假设你可以去:

expect { FactoryGirl.create(:profile, birth_date: 100.days.from_now) }.to raise_error(ActiveRecord::RecordInvalid)

另一种方法是包含 shoulda gem,它具有 allow_value 匹配器。这使您可以在模型规范中做更多类似的事情:

describe Profile, type: :model do
  describe 'Birth date validations' do
    it { should allow_value(100.years.ago).for(:birth_date) }
    it { should_not allow_value(100.days.from_now).for(:birth_date) }
  end
end

通常,当您测试诸如验证之类的东西时,您根本不需要 FactoryGirl。不过,它们在控制器测试中变得非常有用。

只需将模型的断言放在模型规范中,它会直接测试您的模型代码。这些通常存在于 spec/models/model_name_spec.rb 有一些方便的 shoulda 匹配器用于一堆常见的模型东西:

describe SomeModel, type: :model do
  it { should belong_to(:user) }
  it { should have_many(:things).dependent(:destroy) }
  it { should validate_presence_of(:type) }
  it { should validate_length_of(:name).is_at_most(256) }
  it { should validate_uniqueness_of(:code).allow_nil }
end

应该使用 build 而不是 create

另外 profile.valid? 应该在检查 profile.errors

之前调用
it 'birth date cannot be in the future' do
  profile = FactoryGirl.build(:profile, birth_date: 100.days.from_now)
  expect(profile.valid?).to be_falsy
  expect(profile.errors[:birth_date]).to include("the birth date cannot be in the future")
end