【问题标题】:Testing custom validation method with RSpec使用 RSpec 测试自定义验证方法
【发布时间】:2016-08-13 20:51:44
【问题描述】:

我尝试测试检查时间重叠活动的验证方法。

共有三个工厂(其中两个继承自activity)。

工厂:

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

在同一天_of_week(activity.day_of_week == first.day_of_week)、同一 pool_zone(activity.pool_zone == first.pool_zone) 和时间重叠时,活动重叠。

验证方法:

  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

我写了 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

返回:

Failure/Error: expect(first.valid?).to be_falsey

       expected: falsey value
            got: true

我不明白为什么它是真的。首先 create(:activity) 应该是正确的,但 next 不应该被执行(重叠)。 我尝试在expect(first.valid?... 之前添加expect(activity.valid?).to be truthy,但抛出另一个错误ActiveRecord::RecordInvalid。有人可以修复我的测试吗?我是使用 RSpec 创建测试的新手。

更新: 我的问题的解决方案不是 create :first in test 而是 build。 let(:first) { build(:first) }

【问题讨论】:

    标签: ruby-on-rails ruby validation rspec factory-bot


    【解决方案1】:

    这一行单独

    let(:activity) { create(:activity) }
    

    不创建活动。它仅在实际调用 activity 时创建一个活动。因此,在运行测试之前,您必须在某处致电 activity

    有几种方法可以做到这一点,例如前块:

    before { activity }
    

    或者您可以使用let! 而不仅仅是let

    【讨论】:

    • 你说得对。这是有道理的,但就像我提到的 first.valid?返回RecordInvalid。你知道可能是什么原因吗?
    • 创建first 工厂对象时验证失败。检查您在activity.rb 中定义的验证。
    • @Arun 工厂女孩的创建使用保存!以便异常显示您的验证正在触发
    • 您确定您的工厂返回有效实例吗?我的意思是,您是否有单独测试到达工厂的测试(例如 except(build(:activity)).to be_validexcept(create(:activity).errors).to be_empty)?
    • 请调查记录无效的原因。 let(:first) { build(:first).tap { |e| p e.valid?; p e.errors } } 可能会有所帮助...
    猜你喜欢
    • 2014-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多