franckverrot / activevalidators

Collection of ActiveModel/ActiveRecord validators
https://rubygems.org/gems/activevalidators
MIT License
306 stars 49 forks source link

"can't dup nilClass" error in testing with shoulda #72

Closed nadeemkhedr closed 8 years ago

nadeemkhedr commented 10 years ago

User Model

class User < ActiveRecord::Base
  devise :invitable, :database_authenticatable, :registerable, :confirmable,
         :recoverable, :rememberable, :trackable, :validatable
  # other code...
  validates :email, email: true
end

User Spec

 describe User do

  before(:each) { @user = User.new }

  # Validations
  it { expect(@user).to validate_presence_of :username }
  it { expect(@user).to validate_uniqueness_of :username }
  it { expect(@user).to validate_presence_of :full_name }
  it { expect(@user).to validate_presence_of :role }
  it { expect(@user).to ensure_length_of(:password).is_at_least(8) } #FAILS
end

Call Stack

Failure/Error: it { expect(@user).to ensure_length_of(:password).is_at_least(8) }
     TypeError:
       can't dup NilClass
     # /home/nadeem/.rvm/gems/ruby-2.1.2@orbitapp/gems/shoulda-matchers-2.7.0/lib/shoulda/matchers/active_model/helpers.rb:8:in `dup'
     # /home/nadeem/.rvm/gems/ruby-2.1.2@orbitapp/gems/shoulda-matchers-2.7.0/lib/shoulda/matchers/active_model/helpers.rb:8:in `block in pretty_error_messages'
     # /home/nadeem/.rvm/gems/ruby-2.1.2@orbitapp/gems/activemodel-4.1.5/lib/active_model/errors.rb:162:in `block (2 levels) in each'
     # /home/nadeem/.rvm/gems/ruby-2.1.2@orbitapp/gems/activemodel-4.1.5/lib/active_model/errors.rb:162:in `each'
     # /home/nadeem/.rvm/gems/ruby-2.1.2@orbitapp/gems/activemodel-4.1.5/lib/active_model/errors.rb:162:in `block in each'
     # /home/nadeem/.rvm/gems/ruby-2.1.2@orbitapp/gems/activemodel-4.1.5/lib/active_model/errors.rb:161:in `each_key'
     # /home/nadeem/.rvm/gems/ruby-2.1.2@orbitapp/gems/activemodel-4.1.5/lib/active_model/errors.rb:161:in `each'
     # /home/nadeem/.rvm/gems/ruby-2.1.2@orbitapp/gems/shoulda-matchers-2.7.0/lib/shoulda/matchers/active_model/helpers.rb:7:in `map'
     # /home/nadeem/.rvm/gems/ruby-2.1.2@orbitapp/gems/shoulda-matchers-2.7.0/lib/shoulda/matchers/active_model/helpers.rb:7:in `pretty_error_messages'
     # /home/nadeem/.rvm/gems/ruby-2.1.2@orbitapp/gems/shoulda-matchers-2.7.0/lib/shoulda/matchers/active_model/validation_message_finder.rb:34:in `messages_description'
     # /home/nadeem/.rvm/gems/ruby-2.1.2@orbitapp/gems/shoulda-matchers-2.7.0/lib/shoulda/matchers/active_model/allow_value_matcher.rb:293:in `error_description'
     # /home/nadeem/.rvm/gems/ruby-2.1.2@orbitapp/gems/shoulda-matchers-2.7.0/lib/shoulda/matchers/active_model/allow_value_matcher.rb:232:in `failure_message_when_negated'
     # /home/nadeem/.rvm/gems/ruby-2.1.2@orbitapp/gems/shoulda-matchers-2.7.0/lib/shoulda/matchers/active_model/validation_matcher.rb:44:in `allows_value_of'
     # /home/nadeem/.rvm/gems/ruby-2.1.2@orbitapp/gems/shoulda-matchers-2.7.0/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb:336:in `allows_length_of?'
     # /home/nadeem/.rvm/gems/ruby-2.1.2@orbitapp/gems/shoulda-matchers-2.7.0/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb:321:in `allows_minimum_length?'
     # /home/nadeem/.rvm/gems/ruby-2.1.2@orbitapp/gems/shoulda-matchers-2.7.0/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb:295:in `lower_bound_matches?'
     # /home/nadeem/.rvm/gems/ruby-2.1.2@orbitapp/gems/shoulda-matchers-2.7.0/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb:271:in `matches?'
     # ./spec/models/user_spec.rb:12:in `block (2 levels) in <top (required)>'

All tests are passing except the ensure_length_of and its for password not email

To fix this. when i am instantiating the user in the test I have to provide an email

before(:each) { @user = User.new(email: 'user@example.com') }

franckverrot commented 10 years ago

Hi there, thanks for reporting this.

Have you tried passing allow_blank: true on your email validator? Does it change anything?

nadeemkhedr commented 10 years ago

it works when using allow_blank. that said, the rest of the validations works a little different, even if the properties are required and I don't provide them when instantiating the object, the test just works.

Shoulda tests the validations itself not the actual values in the object

franckverrot commented 8 years ago

I'm closing this but feel free to reopen if you think I should do something here. Feels like a shoulda-matchers limitation IMHO, but maybe I'm overlooking something :smile:

Thanks for reporting this in any case!