9

我遇到了一些奇怪的验证行为:它复制了我的验证错误消息,我不知道是什么原因造成的......它在 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 个字符)”……这也是 /only/ 在测试期间发生的。有任何想法吗?

谢谢!

4

4 回答 4

9

问题在于:

Dir["#{Rails.root}/app/**/*.rb"].each { |f| load f }

在 spec_helper.rb 文件中,在 Spork.each_run 块中

如果您将方法“加载”更改为“要求”,它可以解决问题。

或者,如果您有足够新的 Spork 版本,则可以完全删除该行。我很确定当有人使用旧说明安装较新版本的 Spork(0.9.0+) 时会导致错误,因为该行:

Dir["#{Rails.root}/app/**/*.rb"].each { |f| load f }

甚至不再需要在 spec_helper.rb 文件中明确说明。如果是这样,那么当在 spec_helper.rb 文件中使用 load 方法时,它会重新加载指定的文件,这很可能是奇怪的 RSpec 重复验证错误的原因。

于 2012-08-08T20:36:41.093 回答
1

我遇到了类似的重复错误消息问题,但这似乎源于我使用了与标准不同的目录结构,例如:

- 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,所以它可能不相关。

于 2013-02-17T12:22:38.900 回答
0

我有同样的问题(使用 rspec & spork)。

我怀疑这与模型被要求两次有关,导致验证运行两次。

如果您明确地require 'phone'在规范的顶部,它似乎可以解决它。

但我真的很想知道是什么导致了问题...

于 2012-04-25T11:54:34.617 回答
0

我不确定这是否能解决您的问题,但如果您不遵循 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中进行测试。验证的行为应该包含在您的集成测试中。

我希望这会有所帮助。

于 2012-03-13T21:08:32.180 回答