如何使用rspec-rails 3.0.0和shoulda-matcher 2.5.0测试条件验证

时间:2014-03-03 19:54:45

标签: rspec ruby-on-rails-4 shoulda

我正在使用rspec-rails 3.0.0运行Rails 4应用程序并且应该匹配2.5.0,并且我有一个具有一些条件验证的事件模型,如下所示:

class Event < ActiveRecord::Base
  validates :name, :location, :time, :city, :zipcode, :user, :state, presence: true
  validates :post_text, presence: true, if: :happened?
  validates :pre_text, presence: true, unless: :happened?

  belongs_to :community
  belongs_to :user
  belongs_to :state

  def happened?
    (self.time < Time.now) ? true : false
  end
end

我的event_spec.rb看起来像是:

require 'spec_helper'

describe Event do
  before { @event = FactoryGirl.build(:future_event) }

  subject { @event }

  it { should validate_presence_of(:time) }
  it { should validate_presence_of(:name) }
  it { should validate_presence_of(:location) }
  it { should validate_presence_of(:user) }
  it { should validate_presence_of(:city) }
  it { should validate_presence_of(:state) }
  it { should validate_presence_of(:zipcode) }

  it { should belong_to(:state) }
  it { should belong_to(:user) }

  it 'has pre_text if future event' do
     expect(FactoryGirl.create(:future_event)).to be_valid
  end

  it 'has post_text if past event' do
    expect(FactoryGirl.create(:past_event)).to be_valid
  end
end

但是当我运行测试时,我的it { should validate_presence_of(:time) }块失败了,因为它继续运行剩余的验证并在条件验证上抛出异常,因为self.time是nil。我通过检查time.present实现了一个hacky修复程序?在发生了什么?方法。但是,任何人都可以帮助我理解测试需要存在另一个字段的条件验证的最佳方法是什么?

3 个答案:

答案 0 :(得分:4)

这肯定是迟到的,但对于寻求解决方案的其他人来说。我找到了一种有效的方法:

context "if happened" do
  before { allow(subject).to receive(:happened?).and_return(true) }
  it { is_expected.to validate_presence_of(:time) }
end

我希望这会有所帮助

答案 1 :(得分:2)

只是一个小小的提示:

def happened?
  (self.time < Time.now) ? true : false
end

相同
def happened?
  self.time < Time.now
end

答案 2 :(得分:0)

是的,遗憾的是没有其他办法。事实是,在您保存事件记录之前,time在技术上被允许为零,所以如果你恰好打电话给#happened?在time设置之前,引发异常。因此,如果我编写这段代码,我会亲自检查#happened?,因为无论如何都要处理这种情况(无论实际发生的可能性如何)。