FactoryGirl + Rspec自定义验证测试



我对测试很陌生。

我在我的Profile模型中有一个自定义验证

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

在我的工厂。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

在my 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宝石,它具有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有方便的应该匹配器一堆常见的模型的东西:

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.errors之前也应该调用profile.valid?

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

最新更新