2013-02-28 94 views
5

我在我的模型如下验证:RSpec的测试自定义验证

class ContinuumValidator < ActiveModel::Validator 
    def validate(record) 
    if !record.end_time.nil? and record.end_time < record.start_time 
     record.errors[:base] << "An event can not be finished if it did not start yet..." 
    end 
    end 
end 

class Hrm::TimeEvent < ActiveRecord::Base 
    validates_with ContinuumValidator 
end 

如何使用Rspec的我测试它?

这里是我到目前为止已经试过:(感谢zetetic

describe "validation error" do 
    before do 
    @time_event = Hrm::TimeEvent.new(start_time: "2012-10-05 10:00:00", end_time: "2012-10-05 09:00:00", event_type: 2) 
    end 

    it "should not be valid if end time is lower than start time" do 
    @time_event.should_not be_valid 
    end 

    it "raises an error if end time is lower than start time" do 
    @time_event.errors.should include("An event can not be finished if it did not start yet...") 
    end 
end 

,但我得到了以下错误:

1) Hrm::TimeEvent validation error raises an error if end time is lower than start time 
    Failure/Error: @time_event.errors.should include("An event can not be finished if it did not start yet...") 

    expected #<ActiveModel::Errors:0x007fd1d8e02c50 @base=#<Hrm::TimeEvent id: nil, start_time: "2012-10-05 08:00:00", end_time: "2012-10-05 07:00:00", event_type: 2, employee_id: nil, created_at: nil, updated_at: nil, not_punched: false, validated: false, replace_id: nil>, @messages={}> to include "An event can not be finished if it did not start yet..." 

    Diff: 
    @@ -1,2 +1,5 @@ 
    -["An event can not be finished if it did not start yet..."] 
    +#<ActiveModel::Errors:0x007fd1d8e02c50 
    + @base= 
    + #<Hrm::TimeEvent id: nil, start_time: "2012-10-05 08:00:00", end_time: "2012-10-05 07:00:00", event_type: 2, employee_id: nil, created_at: nil, updated_at: nil, not_punched: false, validated: false, replace_id: nil>, 
    + @messages={}> 

我在做什么错?我怎样才能达到我的目标? 任何帮助或建议,将不胜感激。 谢谢。

回答

11

的问题是,你希望@time_event.errors表现得像一个字符串数组。它不,它返回ActiveModel :: Errors。正如其他人所指出的,你还需要触发一个调用验证到valid?

it "raises an error if end time is lower than start time" do 
    @time_event.valid? 
    @time_event.errors.full_messages.should include("An event can not be finished if it did not start yet...") 
end 
+0

你说得对,我需要添加full_messages来获取错误。然而像其他人说的那样,我需要实际测试验证'有效吗?' – siekfried 2013-02-28 13:47:02

+0

没错。我更新了答案。 – 2013-02-28 13:51:01

1

没有错误,因为您没有调用触发错误的事件。这通常在创建或保存记录时发生。您可能不希望击中数据库在您的测试,虽然,然后你可以使用这样的方法valid?

it "raises an error if end time is lower than start time" do 
    @time_event.valid? 
    @time_event.errors.should include("An event can not be finished if it did not start yet...") 
end 

我个人会把这两项测试为一体,因为有效吗?在第一种情况下被称为。

也是次要的:if record.end_timeif !record.end_time.nil?好。 (在我看来,至少...... :-))

+0

你是对的,但像@Benjamin Sullivan建议的,我还需要添加full_messages到错误,以便我的测试通过。也感谢未成年人:) – siekfried 2013-02-28 13:48:49

0

我认为记录没有验证,因此validatior没有运行,也没有发现错误。你可以在代码输出中看到它。 “验证:假”

尝试:

it "raises an error if end time is lower than start time" do 
    @time_event.valid? 
    @time_event.errors.should include("An event can not be finished if it did not start yet...") 
end 
0

您还没有测试验证实际,再加上我会建议你做一个规范。

describe "validation error" do 
    before { @time_event = Hrm::TimeEvent.new(start_time: "2012-10-05 10:00:00", end_time: "2012-10-05 09:00:00", event_type: 2) } 

    it "raises an error if end time is lower than start time" do 
    @time_event.valid? 
    @time_event.errors.should include("An event can not be finished if it did not start yet...") 
    end 
end 

class ContinuumValidator < ActiveModel::Validator 
    def validate(record) 
    if record.end_time and record.end_time < record.start_time 
     record.error.add_to_base << "An event can not be finished if it did not start yet..." 
    end 
    end 
end 
1

该解决方案对我的作品(使用Mongoid):

模型

class OpLog 
... 
field :from_status, type: String 
field :to_status, type: String 
... 
validate :states_must_differ 

def states_must_differ 
    if self.from_status == self.to_status 
    errors.add(:from_status, "must differ from 'to_status'") 
    errors.add(:to_status, "must differ from 'from_status'") 
    end 
end 
... 
end 

测试:

it 'is expected to have different states' do 
    expect { create(:oplog, from_status: 'created', to_status: 'created').to raise_error(Mongoid::Errors::Validations) } 
end 

所以你的情况我d写这样的测试(如果使用ActiveRecord):

it 'raises an error if end time is lower than start time' do 
    expect { create(Hrm::TimeEvent.new(start_time: "2012-10-05 10:00:00", end_time: "2012-10-05 09:00:00", event_type: 2)) }.to raise_error(ActiveRecord::Errors) 
end