我遇到了一些奇怪的验证行为:它重复了我的验证错误消息,并且我无法弄清楚是什么导致了它......它不会在 Rails 控制台中执行此操作。
这是我的手机型号的验证:
# phone.rb
validates :number, :length => { :minimum => 3 }
我的规格:
require 'spec_helper'
describe Phone do
it "requires a number" do
user = User.make!
@p = Phone.new(number:nil,user_id:user.id,type:2)
@p.valid?
puts @p.errors.inspect
@p.should have(1).error_on(:number)
end
我的测试结果:
# rspec and machinist
#<ActiveModel::Errors:0x000000036f1258 @base=#<Phone id: nil, user_id: 614, kind: nil, number: nil, created_at: nil, updated_at: nil>, @messages={:number=>["is too short (minimum is 3 characters)", "is too short (minimum is 3 characters)"]}>
F
Failures:
1) Phone requires a number
Failure/Error: @p.should have(1).error_on(:number)
expected 1 error on :number, got 2
# ./spec/models/phone_spec.rb:11:in `block (2 levels) in <top (required)>'
Finished in 0.50988 seconds
1 example, 1 failure
正如你所看到的,我两次收到“太短(最少 3 个字符)”的消息……这也是/仅/在测试期间发生的。 有什么想法吗?
问题就在这行:
Dir["#{Rails.root}/app/**/*.rb"].each { |f| load f }
在spec_helper.rb文件中,在Spork.each_run块中
如果将方法“load”更改为“require”,问题就可以解决。
或者,如果您有足够新的 Spork 版本,则可以完全删除该行。 我很确定这个错误是当有人使用旧指令安装较新版本的 Spork(0.9.0+) 时引起的,因为该行:
Dir["#{Rails.root}/app/**/*.rb"].each { |f| load f }
甚至不再需要在spec_helper.rb 文件中明确说明。 如果是这样,那么当在spec_helper.rb文件中使用load方法时,它会重新加载指定的文件,很可能是奇怪的RSpec重复验证错误的原因。
我遇到了类似的重复错误消息问题,但这似乎源于我使用了与标准不同的目录结构,例如:
- app
\- models_one
|- models_two
|- models_three
我在
load
块中的 require
/Spork.each_run
调用如下所示:
Dir["#{Rails.root}/app/models_*/*.rb"].each { |f| load f }
我删除了这个并用这些替换了它:
ActiveSupport::Dependencies.clear
ActiveRecord::Base.instantiate_observers
并且不再有重复的错误消息。
这篇文章对我有帮助:http://adams.co.tt/blog/2012/04/12/duplicate-active-model-validation-errors/,其中作者说这是特定于 1.8.7 的问题涉及需要解析为同一文件的不同路径,但我使用的是 1.9.3,因此它可能不相关。
我不确定这是否能解决您的问题,但是如果您不遵循 rspec 约定,则 rspec 会非常奇怪。尝试一些更惯用的 rspec,如下所示:
需要“spec_helper”
describe Phone do
context :validations do
let(:user) { double(:user) }
subject { Phone.new(number:nil,user_id:user.id,type:2) }
before do
subject.valid?
end
it 'should have a minimum length of 3' do
subject.should have(1).error_on(:number)
end
end
end
我还想建议您不要对 Rails 的内置验证进行单元测试;它们已经在 Rails 本身中进行了测试。 具体来说,您的长度验证在 activemodel/test/cases/validations/length_validation_test.rb 中进行测试。 验证的行为应该包含在您的集成测试中。
我希望这对你有帮助。
我遇到了同样的问题(使用 rspec 和 spork)。
我怀疑这与模型被需要两次有关,导致验证运行两次。
如果您在规范顶部明确指出
require 'phone'
,似乎可以修复它。
但是我真的很想知道是什么导致了这个问题......