Peter Tretiakov
Peter Tretiakov

Reputation: 3410

RSpec pass validation test, which should be failed

I have a Company model with attr_accessor :administrator, so when user creates company, he also need to fill some fields for administrator of this company. I'm trying to test, that he fill all fields correctly.

class Company < ActiveRecord::Base
  attr_accessor :administrator

  validates :name, presence: true
  validates :administrator, presence: true, if: :administrator_is_valid?

  private

  def administrator_is_valid?
    administrator[:name].present? and
        administrator[:phone].present? and
        administrator[:email].present? and
        administrator[:password].present? and
        administrator[:password_confirmation].present? and
        administrator[:password] == administrator[:password_confirmation]
  end

end

company_spec.rb is:

require 'rails_helper'

describe Company do

  it 'is valid with name and administrator' do
    company = Company.new(name: 'Company',
    administrator: {
        name: nil,
        email: nil,
        phone: nil,
        password: 'password',
        password_confirmation: ''
    })

    expect(company).to be_valid
  end

end

So, as you see, I have a lot of mistakes in validation test, but RSpec pass it.

Thanks!

Upvotes: 0

Views: 366

Answers (2)

user419017
user419017

Reputation:

You could clean up your code like this:

validate :administrator_is_valid?

private

def administrator_is_valid?
  if administrator_cols_present? && administrator_passwords_match?
    true
  else
    errors.add(:administrator, 'is not valid')
  end
end

def administrator_cols_present?
  %w(name phone email password password_confirmation).all? do |col|
    administrator[col.to_sym].present? # or use %i() instead of to_sym
  end
end

def administrator_passwords_match?
  administrator[:password] == administrator[:password_confirmation]
end

Another improvement might be to move your administrator to a struct, then call valid? on the object.

admin = Struct.new(cols) do
  def valid?
    cols_present? && passwords_match?
  end

  def cols_present?
    cols.values.all? { |col| col.present? }
  end

  def passwords_match?
    cols[:password] == cols[:password_confirmation]
  end
end

Then:

validate :administrator_is_valid?

def admin_struct
  @admin_struct ||= admin.new(administrator)
end

def administrator_is_valid?
  errors.add(:administrator, 'is not valid') unless admin_struct.valid?
end

Upvotes: 1

Ahmad Sherif
Ahmad Sherif

Reputation: 6223

That's because you didn't construct your validation properly. See, if: administrator_is_valid? will return false for your test, telling Rails to skip this validation rule.

I suggest you drop using the presence validator in favor of using administrator_is_valid? method as a validation method, because after all, if the administrator is valid then it is present. The code should look like this

validate :administrator_is_valid?

private

def administrator_is_valid?
    (administrator[:name].present? and
        administrator[:phone].present? and
        administrator[:email].present? and
        administrator[:password].present? and
        administrator[:password_confirmation].present? and
        administrator[:password] == administrator[:password_confirmation]) or
    errors.add(:administrator, 'is not valid')
end

Upvotes: 1

Related Questions