简体   繁体   English

使用RSpec测试自定义验证方法

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM