Model:
validates :email,
uniqueness: {
message: "has been taken."
},
presence: {
message: "cannot be blank."
},
length: {
minimum: 3,
message: "is too short, must be a minimum of 3 characters.",
allow_blank: true
},
format: {
with: /\A[A-Z0-9_\.&%\+\-']+@(?:[A-Z0-9\-]+\.)+(?:[A-Z]{2,13})\z/i,
message: "is invalid.",
if: Proc.new { |u| u.email && u.email.length >= 3 }
}
RSpec:
before(:each) do
@user = FactoryGirl.build(:user)
end
it { should validate_length_of(:email).is_at_least(3) }
Error:
Failure/Error: should validate_length_of(:email).is_at_least(3)
Expected errors to include "is too short (minimum is 3 characters)" when email is set to "xx",
got errors:
* "is too short (minimum is 4 characters)" (attribute: password, value: nil)
* "is too short, must be a minimum of 3 characters." (attribute: email, value: "xx")
* "is not included in the list" (attribute: state, value: "passive")
Factory:
factory :user, class: User do
email FFaker::Internet.email
password FFaker::Internet.password
username FFaker::Internet.user_name
end
I am using factory_girl_rails with shoulda_matchers. Every time I try to validate my email, I keep getting an error like above. It says the email value is "xx", but the length of the factory email is greater than that. How can I write an rspec that will pass?
You are understanding the error (and it's cause) wrong. The error says that it expects "is too short (minimum is 3 characters)" but in the errors it can't find that string (rspec finds "is too short, must be a minimum of 3 characters." which is what you defined on your validation).
When you use shoulda matchers and say
I'm guessing it creates a test with an email shorter than 3 and checks if it fails, that's why it's ignoring your factory, internally should matcher is setting a fixed length string just to make that test pass.
When you see the errors in user, that test should actually work since the error is actually there, only the string is different. So, you have two options: remove the custom message when length is minimum: 3; or tell the matcher what message you are expecting: