Rails 3: Duplicate validation error messages during testing
I'm getting some weird validation behavior: it's duplicating my validation error messages and I can't figure out what's causing it... it doesn't do this in the rails console.
Here is the validation from my Phone model:
# phone.rb
validates :number, :length => { :minimum => 3 }
My spec:
开发者_Go百科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
My test results:
# 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
As you can see, I'm getting "is too short (minimum is 3 characters)" twice... It's also /only/ happening during testing. Any ideas?
Thanks!
The problem is in the line:
Dir["#{Rails.root}/app/**/*.rb"].each { |f| load f }
in the spec_helper.rb file, in the Spork.each_run block
If you change the method 'load' to 'require', it fixes the problem.
Or if you have a recent enough version of Spork, you can remove the line altogether. I am pretty sure the error is caused when someone is installing a newer version Spork(0.9.0+) with old instructions, because the line:
Dir["#{Rails.root}/app/**/*.rb"].each { |f| load f }
doesn't even has to be stated explicitly in the spec_helper.rb file anymore. If it is then when the load method is used in the spec_helper.rb file, it reloads the files specified , most likely the cause of the strange RSpec duplicate validations errors.
I encountered a similar issue of duplicate error messages, but it seemed to stem from my use of a different directory structure than the standard, e.g.:
- app
\- models_one
|- models_two
|- models_three
My load
/require
call in the Spork.each_run
block looked like this:
Dir["#{Rails.root}/app/models_*/*.rb"].each { |f| load f }
I removed this and replaced it with these:
ActiveSupport::Dependencies.clear
ActiveRecord::Base.instantiate_observers
And there were no more duplicate error messages.
I was helped by this post: http://adams.co.tt/blog/2012/04/12/duplicate-active-model-validation-errors/ in which the author says it's a 1.8.7-specific problem which involves requiring different paths which resolve to the same file, but I am using 1.9.3 so it may not be related.
I'm not sure if this is going to solve your problem, but rspec is very quirky if you don't follow rspec convention. Try some more idiomatic rspec like the following:
require '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
I'd also like to suggest that you shouldn't unit test Rails' built in validations; they are already tested in Rails itself. Specifically, your length validation is tested in activemodel/test/cases/validations/length_validation_test.rb. The behavior of the validations should be covered in your integration tests.
I hope that's helpful.
I'm having the same problem (using rspec & spork).
I suspect it's something to do with the model being required twice, causing validations to run twice.
If you explicity require 'phone'
at the top of your spec, it seems to fix it.
But I'd really like to know what's causing the problem...
精彩评论