FactoryGirl Rspec创建无效实例

时间:2014-07-11 19:23:15

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

所以我有一个围绕日历上的事件的应用程序。事件有一个starts_at和ends_at。添加了一项新要求,以限制新事件的创建仅限于将来,更具体地说,>今天午夜。很自然地,我修改了我的validate方法以在实例化时检查它。但是,当使用FactoryGirl进行RSpec测试时,这会产生问题。

许多测试需要检查过去事件的某些要求。问题是,我不能再创建那些元素,因为它验证失败了。所以我找到了一些方法来解决这个问题

allow(instance)to receive(:starts_at).and_return(some_future_time)

expect_any_instance_of(Event).to receive(:check_valid_times).and_return(true)

这是来自应用程序的一些简单代码

#Model
class Event < ActiveRecord::Base
  validate :check_for_valid_times

  private:
    def check_for_valid_times
      if starts_at.present? && (starts_at < Time.now.at_beginning_of_day)
        errors.add(:base, I18n.t('event.start_time_before_now'))
      end
      unless starts_at.present? && (starts_at < ends_at)
        errors.add(:base, I18n.t('event.end_time_before_start'))'
      end
    end
end

我的工厂

#factory
require 'factory_girl'

FactoryGirl.define do
  factory :event do
    starts_at { 2.hour.from_now.to_s }
  end
end

问题:有没有一个很好的干净方法来做这个而不是必须处理每个事件的创建并在我的所有测试中专门处理它们?目前,我不得不以不同的方式处理其中的一些。

如果我要发布代码的其他部分,请告诉我。

一如既往,提前感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

我通常解决这类问题的方法是timecop gem。

例如:

Timecop.freeze 1.hour.ago do
  create(:event)
end

然后,您可以将这些内容放在let块中,或放在spec/support/events.rb中的帮助中,以使其保持干燥和可维护状态。

使用timecop,您可以完全模拟测试。因此,在过去您正在关注的时间正确创建事件,然后将时间恢复正常,并查看您的测试显示事件已过去且无法更改,依此类推。它允许完整,准确和易于理解的时间敏感测试。 RSpec帮助程序,共享上下文和before / let块可以处理保持测试清洁。