RSpec通过验证测试,应该失败

时间:2014-09-28 22:11:25

标签: ruby-on-rails ruby-on-rails-4 rspec

我有一个Company模型attr_accessor :administrator,因此当用户创建公司时,他还需要为该公司的管理员填写一些字段。我试图测试,他正确填写所有字段。

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是:

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

所以,正如你所看到的,我在验证测试中有很多错误,但是RSpec通过它。

谢谢!

2 个答案:

答案 0 :(得分:1)

那是因为您没有正确构建验证。请参阅,if: administrator_is_valid?将为您的测试返回false,告诉Rails跳过此验证规则。

我建议你使用在线验证器,而不是使用administrator_is_valid?方法作为验证方法,因为毕竟,如果管理员有效,那么它就存在了。代码应如下所示

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

答案 1 :(得分:1)

您可以像这样清理代码:

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

另一项改进可能是将administrator移至结构,然后在对象上调用valid?

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

然后:

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