Search code examples
ruby-on-railsvalidationruby-on-rails-4rspecrspec-rails

Rails code validation working but Rspec tests failing


Can anyone see what's wrong about the Rspec? All of my tests for invalid emails are failing (i.e., they are supposed to not be valid but somehow are in Rspec), but in the actual code, it works fine, no emails that are bad are allowed. The validation even works in my console....

Two notes:

  1. I realize the formatting isn't ideal... will work on that later. This was just me writing things individually without going through and DRYing it up yet.
  2. I also realize there exists an easier way to validate these things individually in the model, but I wanted very custom messages without any reference to the attribute, and I disliked the roundabout way that I've read that needs to be done.

Model code

validate :create_validation, on: :create

def create_validation
    errors[:base] << "Please enter a valid email address to continue" if self.email.blank? || (( /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i =~ self.email) == nil) 
end
#The RegEx is from Michael Hartl's tutorial

Spec code

describe Signup do

before do
    @signup = FactoryGirl.create(:signup)
end

    subject { @signup }

    describe "email tests" do
      describe "invalid tests" do 
        # blank email
        before { @signup.email = " " }
        it { should_not be_valid }

        # invalid format email
        addresses = %w[[email protected], user@foo,com user_at_foo.org example.user@foo. foo@bar_baz.com foo@bar+baz.com]
        addresses.each do |invalid_address|
          before { @signup.email = invalid_address }
          it { should_not be_valid }
        end
      end
    end
end

Factory girl code in spec helper

FactoryGirl.define do
  factory :signup do |f|
    f.email { Faker::Internet.email }
            #... other attributes
  end

end


Solution

  • As I understood code you validate only on create! But in tests you created object in before block and it is persisted in your tests - so validation is skipped.

    Try this variant

    describe Signup do
    
      before do
        @signup = FactoryGirl.build(:signup)
      end
    
      subject { @signup }
    
      describe "email tests" do
        describe "invalid tests" do 
          # blank email
          before { @signup.email = " " }
    
          it { should_not be_valid }
    
          # invalid format email
          addresses = %w[[email protected], user@foo,com user_at_foo.org example.user@foo. foo@bar_baz.com foo@bar+baz.com]
          addresses.each do |invalid_address|
    
            before { @signup.email = invalid_address }
            it { should_not be_valid }
          end
        end
      end
    end
    

    I hope validation will be triggered for built but not saved record.

    PS Or you can remove option on: :create