[英]Testing custom validation method with RSpec
I try to test validation method that check times overlap for activities. 我尝试测试确认时间是否与活动重叠的验证方法。
There are three factories(two of them inherit from activity). 有三个工厂(其中两个从活动继承)。
Factories: 工厂:
activities.rb Activities.rb
FactoryGirl.define do
factory :activity do
name 'Fit Girls'
description { Faker::Lorem.sentence(3, true, 4) }
active true
day_of_week 'Thusday'
start_on '12:00'
end_on '13:00'
pool_zone 'B'
max_people { Faker::Number.number(2) }
association :person, factory: :trainer
factory :first do
name 'Swim Cycle'
description 'Activity with water bicycles.'
active true
day_of_week 'Thusday'
start_on '11:30'
end_on '12:30'
end
factory :second do
name 'Aqua Crossfit'
description 'Water crossfit for evereyone.'
active true
day_of_week 'Thusday'
start_on '12:40'
end_on '13:40'
pool_zone 'C'
max_people '30'
end
end
end
Activities overlaps when are on same day_of_week(activity.day_of_week == first.day_of_week), on same pool_zone(activity.pool_zone == first.pool_zone) and times overlaps. 当活动在同一day_of_week(activity.day_of_week == first.day_of_week),同一pool_zone(activity.pool_zone == first.pool_zone)上时,活动重叠,并且时间重叠。
Validation method: 验证方法:
def not_overlapping_activity
overlapping_activity = Activity.where(day_of_week: day_of_week)
.where(pool_zone: pool_zone)
activities = Activity.where(id: id)
if activities.blank?
overlapping_activity.each do |oa|
if (start_on...end_on).overlaps?(oa.start_on...oa.end_on)
errors.add(:base, "In this time and pool_zone is another activity.")
end
end
else
overlapping_activity.where('id != :id', id: id).each do |oa|
if (start_on...end_on).overlaps?(oa.start_on...oa.end_on)
errors.add(:base, "In this time and pool_zone is another activity.")
end
end
end
end
I wrote rspec test, but unfortunatelly invalid checks. 我写了rspec测试,但不幸的是检查无效。
describe Activity, 'methods' do
subject { Activity }
describe '#not_overlapping_activity' do
let(:activity) { create(:activity) }
let(:first) { create(:first) }
it 'should have a valid factory' do
expect(create(:activity).errors).to be_empty
end
it 'should have a valid factory' do
expect(create(:first).errors).to be_empty
end
context 'when day_of_week, pool_zone are same and times overlap' do
it 'raises an error that times overlap' do
expect(activity.valid?).to be_truthy
expect(first.valid?).to be_falsey
expect(first.errors[:base].size).to eq 1
end
end
end
end
Return: 返回:
Failure/Error: expect(first.valid?).to be_falsey
expected: falsey value
got: true
I can't understand why it got true. 我不明白为什么会这样。 First create(:activity) should be right, but next shouldn't be executed(overlapping). 首先create(:activity)应该是正确的,但是接下来不应该执行(重叠)。 I tried add expect(activity.valid?).to be truthy
before expect(first.valid?...
, but throws another error ActiveRecord::RecordInvalid
. Could someone repair my test? I'm newbie with creation tests using RSpec. 我试过expect(activity.valid?).to be truthy
expect(first.valid?...
expect(activity.valid?).to be truthy
之前添加expect(activity.valid?).to be truthy
,但是抛出另一个错误ActiveRecord::RecordInvalid
。有人可以修复我的测试吗?我是使用RSpec进行创建测试的新手。
UPDATE: Solution for my problem is not create :first in test but build. 更新:我的问题的解决方案不是在测试中创建:first而是在构建。 let(:first) { build(:first) }
This line on its own 这条线自己
let(:activity) { create(:activity) }
doesn't create an activity. 不会创建活动。 It only creates an activity, when activity
is actually called. 仅在实际调用activity
时才创建活动。 Therefore you must call activity
somewhere before running your test. 因此,您必须在运行测试之前在某处调用activity
。
There are several ways to do so, for example a before block: 有几种方法可以做到这一点,例如一个before块:
before { activity }
or you could use let!
或者您可以使用let!
instead of just let
. 而不是仅仅let
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.