35 votos

Cómo probar un validador personalizado?

Tengo el siguiente validador:

# Source: http://guides.rubyonrails.org/active_record_validations_callbacks.html#custom-validators
# app/validators/email_validator.rb

class EmailValidator < ActiveModel::EachValidator
  def validate_each(object, attribute, value)
    unless value =~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
      object.errors[attribute] << (options[:message] || "is not formatted properly") 
    end
  end
end

Me gustaría ser capaz de poner a prueba esta en RSpec dentro de mi directorio lib. El problema hasta ahora es que no estoy seguro de cómo inicializar un EachValidator.

63voto

Neal Puntos 1594

Yo no soy un gran fan de el otro enfoque porque vincula la prueba demasiado cerca de la aplicación. También, es bastante difícil de seguir. Este es el enfoque que utilice en última instancia. Por favor, tenga en cuenta que esto es una burda simplificación de lo que mi validador hizo... sólo quería demostrar que es más simple. Definitivamente hay optimizaciones para ser realizados

class OmniauthValidator < ActiveModel::Validator
  def validate(record)
    if !record.omniauth_provider.nil? && !%w(facebook github).include?(record.omniauth_provider)
      record.errors[:omniauth_provider] << 'Invalid omniauth provider'
    end
  end
end

Asociados De Especificaciones:

require 'spec_helper'

class Validatable
  include ActiveModel::Validations
  validates_with OmniauthValidator
  attr_accessor  :omniauth_provider
end

describe OmniauthValidator do
  subject { Validatable.new }

  context 'without provider' do
    it 'is valid' do
      expect(subject).to be_valid
    end
  end

  context 'with valid provider' do
    it 'is valid' do
      subject.stubs(omniauth_provider: 'facebook')

      expect(subject).to be_valid
    end
  end

  context 'with unused provider' do
    it 'is invalid' do
      subject.stubs(omniauth_provider: 'twitter')

      expect(subject).not_to be_valid
      expect(subject).to have(1).error_on(:omniauth_provider)
    end
  end
end

Básicamente, mi enfoque es crear un falso objeto "Validable", de modo que podemos poner a prueba los resultados en lugar de tener expectativas para cada parte de la aplicación

39voto

Gazler Puntos 23588

He aquí un rápido spec llamé para ese archivo y funciona bien. Creo que la intermitencia probablemente podría ser limpiado, pero esperemos que esto será suficiente para empezar.

require 'spec_helper'


describe "EmailValidator" do

  before(:each) do
    @validator = EmailValidator.new({:attributes => {}})
    @mock = mock('model')
    @mock.stub("errors").and_return([])
    @mock.errors.stub('[]').and_return({})  
    @mock.errors[].stub('<<')
  end

  it "should validate valid address" do
    @mock.should_not_receive('errors')    
    @validator.validate_each(@mock, "email", "test@test.com")
  end

  it "should validate invalid address" do
    @mock.errors[].should_receive('<<')
    @validator.validate_each(@mock, "email", "notvalid")
  end  
end

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by: