Ruby on rails 在没有数据库的情况下,如何在ActiveRecord模型规范中模拟唯一性验证错误?
我有一个ActiveRecord模型,上面有唯一性验证:Ruby on rails 在没有数据库的情况下,如何在ActiveRecord模型规范中模拟唯一性验证错误?,ruby-on-rails,activerecord,rspec,activemodel,Ruby On Rails,Activerecord,Rspec,Activemodel,我有一个ActiveRecord模型,上面有唯一性验证: class Profile < ActiveRecord::Base # fields: :name, :slug before_validation :set_default_slug_from_name validates :slug, uniqueness: {case_sensitive: false}, unless: -> { |p| p.slug.blank?
class Profile < ActiveRecord::Base
# fields: :name, :slug
before_validation :set_default_slug_from_name
validates :slug, uniqueness: {case_sensitive: false},
unless: -> { |p| p.slug.blank? }
# ...
end
我深入研究了实现uniquenessvalidater
的
allow_any_instance_of(ActiveRecord::Relation).to receive(:exists?).and_return(true)
# ...
但这似乎不起作用。我想你在这里想得有点太深了。虽然阅读rails源代码并理解其工作原理非常好,但模仿rails内部使用的每个类实例并不是一个好主意。在这种情况下,UniquenessValidator与其他一些验证器不同,它确实依赖于数据库,因此您应该: a。允许自己点击数据库。在这种情况下,这不是一个巨大的开销,而且可能是实现这一点的最实际的方法。你甚至在你的规范中的注释中使用了“复制记录”,那么为什么不在那里有一个记录呢?在10个案例中,有9个是正确的方法。毕竟,您正在检查一种ActiveRecord::Base对象 b。检查独立于rails验证的行为。无论如何都应该这样做,以测试您首选的slug格式。最好在验证之前确保默认slug有效。 这里的缺点是,在这次调用和实际验证之前,slug很可能会被其他人使用,但Rails内置验证也是如此,所以我不必担心——您最终会出错,下一次尝试很可能会成功
it "modifies the beginning of the slug on validation if there is a duplicate" do
Profile.stub(:slug_exists?).with("bob-greenfield").and_return(true)
Profile.stub(:slug_exists?).with("1-bob-greenfield").and_return(true)
Profile.stub(:slug_exists?).with("2-bob-greenfield").and_return(false)
subject.set_default_slug_from_name
subject.slug.should == "2-bob-greenfield"
end
而且您已经知道Rails在验证之前调用,所以您不必测试这种行为
此外,最好确保对数据库有约束,Rails的唯一性是不够的:
it "modifies the beginning of the slug on validation if there is a duplicate" do
Profile.stub(:slug_exists?).with("bob-greenfield").and_return(true)
Profile.stub(:slug_exists?).with("1-bob-greenfield").and_return(true)
Profile.stub(:slug_exists?).with("2-bob-greenfield").and_return(false)
subject.set_default_slug_from_name
subject.slug.should == "2-bob-greenfield"
end